方式一:通过线程池或者进程池
导入库futures是python3自带的库,如果是python2,需要pip安装future这个库
备注:进程池和线程池写法相同
 from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from tornado.concurrent import run_on_executor def doing(s):
print('xiumian--{}'.format(s))
time.sleep(s)
return s class MyMainHandler(RequestHandler):
executor = ProcessPoolExecutor(2) #新建一个进程池,静态变量,属于类,所以全程只有这个几个进程,不需要关闭,如果放在__init__中,则属于对象,每次请求都会新建pool,当请求增多的时候,会导致今天变得非常多,这个方法不可取 @gen.coroutine
def get(self, *args, **kwargs):
print('开始{}'.format(self.pool_temp))
a = yield self.executor.submit(doing, 20)
print('进程 %s' % self.executor._processes)
self.write(str(a))
print('执行完毕{}'.format(a)) @run_on_executor #tornado 另外一种写法,需要在静态变量中有executor的进程池变量
def post(self, *args, **kwargs):
a = yield doing(20)
方式二:Tornado + Celery + RabbitMQ 实现
使用Celery任务队列,Celery 只是一个任务队列,需要一个broker媒介,将耗时的任务传递给Celery任务队列执行,执行完毕将结果通过broker媒介返回。官方推荐使用RabbitMQ作为消息传递,redis也可以
 
一、Celery 介绍:
1.1、注意:
1、当使用RabbitMQ时,需要按照pika第三方库,pika0.10.0存在bug,无法获得回调信息,需要按照0.9.14版本即可
2、tornado-celery 库比较旧,无法适应Celery的最新版,会导致报无法导入task Producter包错误,只需要将celery版本按照在3.0.25就可以了
 
1.2、关于配置:
单个参数配置:
  app.conf.CELERY_RESULT_BACKEND = 'redis://localhost:6379/0' 
多个参数配置:
 app.conf.update(
CELERY_BROKER_URL = 'amqp://guest@localhost//',
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
)
从配置文件中获取:(将配置参数写在文件app.py中)
 BROKER_URL='amqp://guest@localhost//'
CELERY_RESULT_BACKEND='redis://localhost:6379/0'
app.config_from_object('celeryconfig')
 
 
二、案例
2.1、启动一个Celery 任务队列,也就是消费者:
 from celery import Celery
celery = Celery('tasks', broker='amqp://guest:guest@119.29.151.45:5672', backend='amqp') 使用RabbitMQ作为载体, 回调也是使用rabbit作为载体 @celery.task(name='doing') #异步任务,需要命一个独一无二的名字
def doing(s, b):
print('开始任务')
logging.warning('开始任务--{}'.format(s))
time.sleep(s)
return s+b
命令行启动任务队列守护进程,当队列中有任务时,自动执行 (命令行可以放在supervisor中管理)
--loglevel=info --concurrency=5
记录等级,默认是concurrency:指定工作进程数量,默认是CPU核心数
 
2.2、启动任务生产者
 import tcelery
tcelery.setup_nonblocking_producer() #设置为非阻塞生产者,否则无法获取回调信息 class MyMainHandler(RequestHandler): @web.asynchronous
@gen.coroutine
def get(self, *args, **kwargs):
print('begin')
result = yield gen.Task(sleep.apply_async, args=[10]) #使用yield 获取异步返回值,会一直等待但是不阻塞其他请求
print('ok--{}'.format(result.result)) #返回值结果 # sleep.apply_async((10, ), callback=self.on_success)
# print('ok -- {}'.format(result.get(timeout=100)))#使用回调的方式获取返回值,发送任务之后,请求结束,所以不能放在处理tornado的请求任务当中,因为请求已经结束了,与客户端已经断开连接,无法再在获取返回值的回调中继续向客户端返回数据 # result = sleep.delay(10) #delay方法只是对apply_async方法的封装而已
# data = result.get(timeout=100) #使用get方法获取返回值,会导致阻塞,相当于同步执行 def on_success(self, response): #回调函数
print ('Ok-- {}'.format(response))
 
 
 
 
 
 
 
 

Tornado 高并发源码分析之六---异步编程的几种实现方式的更多相关文章

  1. Tornado 高并发源码分析之四--- HTTPServer 与 TCPServer 对象

    主要工作: 服务器启动的时候做的事: 1.把包含了各种配置信息的 application 对象封装到了 HttpServer 对象的 request_callback 字段中,等待被调用 2.TCPS ...

  2. Tornado 高并发源码分析之五--- IOLoop 对象

    IOLoop主要工作 1.将TCPServer 注册到 IOLoop 的事件记到 _handlers 字段,同时注册 READ 和 ERROR 事件到 epoll 2.IOLoop 启动一个大循环,负 ...

  3. Tornado 高并发源码分析之三--- Application 对象

    Application 对象主要工作: 服务器启动时: 1.在新建一个app的时候,根据设置好的 URL 和回调函数 Handler 封装成URLSpec 对象   服务器运行时: 2.在请求到来,将 ...

  4. Tornado 高并发源码分析之二---Tornado启动和请求处理流程

    Tornado 服务器启动流程 因为Tornado 里使用了很多传类的方式,也就是delegate,之所以要这么做,其实和 iOS 开发那样,也很多的 delegate, 如此来实现高度解耦,但是比较 ...

  5. Tornado 高并发源码分析之一---启动一个web服务

    前言: 启动一个tornado 服务器基本代码 class HomeHandler(tornado.web.RequestHandler): #创建 RequesHandler 对象,处理接收到的 h ...

  6. ViewGroup事件分发源码分析

    1.AndroidStudio源码调试方式 AndroidStudio默认是支持一部分源码调试的,但是build.gradle(app) 中的sdk版本要保持一致, 最好是编译版本.运行版本以及手机的 ...

  7. v76.01 鸿蒙内核源码分析(共享内存) | 进程间最快通讯方式 | 百篇博客分析OpenHarmony源码

    百篇博客分析|本篇为:(共享内存篇) | 进程间最快通讯方式 进程通讯相关篇为: v26.08 鸿蒙内核源码分析(自旋锁) | 当立贞节牌坊的好同志 v27.05 鸿蒙内核源码分析(互斥锁) | 同样 ...

  8. 鸿蒙内核源码分析(内存分配篇) | 内存有哪些分配方式  | 百篇博客分析OpenHarmony源码 | v11.02

    百篇博客系列篇.本篇为: v11.xx 鸿蒙内核源码分析(内存分配篇) | 内存有哪些分配方式 | 51.c.h .o 内存管理相关篇为: v11.xx 鸿蒙内核源码分析(内存分配篇) | 内存有哪些 ...

  9. Java 异步编程的几种方式

    前言 异步编程是让程序并发运行的一种手段.它允许多个事情同时发生,当程序调用需要长时间运行的方法时,它不会阻塞当前的执行流程,程序可以继续运行,当方法执行完成时通知给主线程根据需要获取其执行结果或者失 ...

随机推荐

  1. ControllerDescriptor的认识

    ControllerDescriptor类主要包含了对ASP.NET MVC中的Control的元数据的解析,在MVC的Model绑定以及数据处理过程中经常会遇到ControllerDescripto ...

  2. oracle objects - Materialized views and Synonyms

    Materialized views - 物化视图,不实时查询表,定期更新,查询速度快 视图的更新频率我们可以在这看到:select * from dba_jobs , 一般在创建视图的时候完成的. ...

  3. python练习题100例

    链接地址:http://www.runoob.com/python/python-100-examples.html

  4. mybatis分页插件使用注意

    之前的项目用的数据库是mysql,在pom.xml引入这一个就能分页了. 后来又开了一个项目,使用的是oracle数据库,我写分页的时候发现不能实现,在网上找到资料说是必须要5.0以上的.我就导了这依 ...

  5. TCP与UDP(实时通讯)

    1.TCP使用 导入AsyncSocket资源文件夹,此文件是arc混编,加入库文件,如下图: #import "ViewController.h" #import "A ...

  6. New Concept English three (38)

    26w/m 45 Future historians will be in a unique position when they come to record the history of our ...

  7. 类Flask实现前后端交互之代码聊天室

    前言 框架 项目目录及各自功能 流程图 后端 server backend exector 前端 ajax 页面更新 演示 简易应答模式 代理模式处理外部请求 后台日志 总结 前言 这两天老是做梦,全 ...

  8. mac地址常识及获取

    mac常识: 网卡地址这个概念有点混淆不清.因为实际上有两个地址,mac地址和物理地址,一般说网卡地址我是指物理地址,不知道别人怎么看?物理地址指的是网卡上的存放地址的ROM里的地址,mac地址是这块 ...

  9. 深入了解zookeeper(三)

    一.ZooKeeper 的实现 1.1 ZooKeeper处理单点故障 我们知道可以通过ZooKeeper对分布式系统进行Master选举,来解决分布式系统的单点故障,如图所示. 那么我们继续分析一下 ...

  10. JS 隔行变色

    <script type="text/javascript">       window.onload=function(){             var oUl= ...