方式一:通过线程池或者进程池
导入库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. PHP生成UTF-8编码的CSV文件用Excel打开乱码的问题

    在你要输出的内容前先输出"\xEF\xBB\xBF",例如:你要输出的内容保存在$content里$content = "\xEF\xBB\xBF".$cont ...

  2. Excel 读写操作

    读 import xlrd from xlrd.book import Book from xlrd.sheet import Sheet from xlrd.sheet import Cell wo ...

  3. Android面试题整理

    1.    请描述下Activity的生命周期. 2.    如果后台的Activity由于某原因被系统回收了,如何在被系统回收之前保存当前状态? 3.    如何将一个Activity设置成窗口的样 ...

  4. Arcgis for Js之Graphiclayer扩展详解

    在前两节,讲到了两种不同方式的聚类,一种是基于距离的,一种是基于区域范围的,两种不同的聚类都是通过扩展esri/layers/GraphicsLayer方法来实现的.在本节,就详细的讲讲esri/la ...

  5. auto_ptr, unique_ptr, shared_ptr and weak_ptr智能指针讲解

    笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...

  6. HAWQ取代传统数仓实践(十三)——事实表技术之周期快照

    一.周期快照简介 周期快照事实表中的每行汇总了发生在某一标准周期,如一天.一周或一月的多个度量.其粒度是周期性的时间段,而不是单个事务.周期快照事实表通常包含许多数据的总计,因为任何与事实表时间范围一 ...

  7. js将json数据动态生成表格

    今天开发中遇到需要展示动态数据的问题, 具体要求是后端传来的json字符串,要在前端页面以table表格的形式展示, 其实没啥难的,就是拼接table标签,纯属体力活,于是自己写了个呆萌,保存起来,以 ...

  8. 解决 Laravel/Lumen 出现 "Please provide a valid cache path" 问题

    解决 Laravel/Lumen 出现 "Please provide a valid cache path" 问题 解决 Laravel/Lumen 出现 "Pleas ...

  9. kali学习

    kali视频学习 第二周 kali视频(1-5) 1.kali安装 2.基本配置 vmtools安装过程. 3.安全渗透测试一般流程 4.信息搜集之GoogleHack 5.信息搜集之目标获取 第三周 ...

  10. sql_自连接,181,182,196,197

    181. Employees Earning More Than Their Managers https://leetcode.com/problems/employees-earning-more ...