1、使用 tornado.gen.coroutine 异步编程(需要第三方库支持tornado异步)
同步阻塞
-
code
# coding=utf-8 # @Time : 2020/11/3 15:40 # @Author : Leo # @Email : l1512102448@qq.com # @File : demo_tornado_asy.py import tornado.web import tornado.ioloop import tornado.gen as gen import time class LeoHandler(tornado.web.RequestHandler): """ Tornado同步 """ # @gen.coroutine def get(self): print(1) # 异步执行 # yield gen.sleep(10) time.sleep(10) print(2) self.write("hello") if __name__ == '__main__': app = tornado.web.Application([ (r"/leo", LeoHandler), ]) app.listen(8888) tornado.ioloop.IOLoop.current().start()
-
ab接口压力测试结果
控制台可以看出请求是阻塞状态
异步非阻塞
- code
# coding=utf-8
# @Time : 2020/11/3 15:40
# @Author : Leo
# @Email : l1512102448@qq.com
# @File : demo_tornado_asy.py
import tornado.web
import tornado.ioloop
import tornado.gen as gen
import time
class LeoHandler(tornado.web.RequestHandler):
"""
异步的延时10秒接口,gen.sleep支持Tornado异步
"""
@gen.coroutine
def get(self):
print(1)
# 异步执行
yield gen.sleep(10)
print(2)
self.write("hello")
if __name__ == '__main__':
app = tornado.web.Application([
(r"/leo", LeoHandler),
])
app.listen(8888)
tornado.ioloop.IOLoop.current().start()
- ab接口压力测试结果
控制台结果表明请求是异步的,没有被阻塞
2、基于线程的异步编程
使用 tornado.gen.coroutine 装饰器编写异步函数,如果库本身不支持异步,那么响应仍然是阻塞的。
在 Tornado 中有个装饰器能使用 ThreadPoolExecutor 来让阻塞过程变成非阻塞,其原理是在 Tornado 本身这个线程之外另外启动一个线程来执行阻塞的程序,从而让 Tornado 变得非阻塞。
-
code
class LeoThreadHandler(tornado.web.RequestHandler): ''' 基于线程实现异步非阻塞 ''' # 必须定义一个executor的属性,然后run_on_executor 注解才管用。 executor = ThreadPoolExecutor(max_workers=10) @run_on_executor def sleep_fun(self): time.sleep(5) @gen.coroutine def get(self): print(1) # 异步执行 yield self.sleep_fun() print(2) self.write("hello") if __name__ == '__main__': app = tornado.web.Application([ (r"/leo", LeoThreadHandler), ]) app.listen(8888) tornado.ioloop.IOLoop.current().start()
-
ab压力测试结果
- 分析
虽然tornado.gen.coroutine结合线程池实现了异步非阻塞, 但是与之而来的问题是,如果大量使用线程化的异步函数做一些高负载的活动,会导致该 Tornado 进程性能低下响应缓慢,这只是从一个问题到了另一个问题而已。
所以在处理一些小负载的工作,是能起到很好的效果,让 Tornado 异步非阻塞的跑起来。
3、基于 Celery 的异步编程
4、 python的原生协程关键字:Async和Await
前言
- Async用来声明一个函数为异步函数
异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件(假设挂起条件是sleep(5))消失后,也就是5秒到了再回来执行。
-
Await 用来声明程序挂起,挂起后继续执行
-
code
class AsynchronousSleepHandler(tornado.web.RequestHandler): ''' python的原生协程关键字:Async和Await实现异步 ''' async def get(self): print(1) await asyncio.sleep(5) print(2) self.write("hello") if __name__ == '__main__': app = tornado.web.Application([ (r"/leo", AsynchronousSleepHandler), ]) app.listen(8888) tornado.ioloop.IOLoop.current().start()
-
ab压力测试结果