Python Tornado 异步处理实现

本文将叙述如何利用线程池的方式实现Tornado的异步处理。
1. 异步处理方案 在处理请求应用上加上@tornado.web.asynchronous和@tornado.gen.engine装饰器,即可实现异步方法配合实现非阻塞请求处理。请求上加了这两个装饰器,@tornado.web.asynchronous装饰器表明该请求不会自动断掉输出流,且需要显式的调用finish方法。此外,asynchronous需要和@tornado.gen.engine搭配使用。
请求在没有加上装饰器@tornado.web.asynchronous时,get(post)方法结束后,请求会自动断开,但是加上这个装饰器后,get请求可以直接return且保持连接,直到显式的调用finish方法才会关闭输出流。即,在接受到请求后,get(post)方法直接交给别的函数来处理,处理完后再由get(post)方法调用finish()来关闭输出流。
但是,当异步处理函数里有死循环导致get(post)处理函数阻塞,亦不能让服务器处理别的请求。因为Tornado是单线程事件驱动模式的服务器,一旦方法阻塞,必然导致服务器阻塞。不过,依然有办法处理这种情况,那就是开启多线程。
2. 异步处理实现

#-*- coding:utf-8 -*- import tornado.httpserver import tornado.ioloop import tornado.options import tornado.web import os.path import logging import time from tornado.concurrent import run_on_executor from concurrent.futures import ThreadPoolExecutor from tornado.options import define, options# 绝对路径 tool_path = os.path.abspath(os.path.dirname(__file__))# log config logging.basicConfig(level=logging.DEBUG,format="[%(asctime)s] %(levelname)s %(message)s", datefmt="%Y-%m-%d %H:%M:%S")#定义端口为8888 define("port", default=8888, help="run on the given port", type=int)# POST请求 class IndexHandler(tornado.web.RequestHandler): # 线程池 max_thread_num = 10 executor = ThreadPoolExecutor(max_workers=max_thread_num)# 线程内处理 @run_on_executor #@tornado.gen.coroutine 支持异步处理 def my_func(self): # do your thing time.sleep(10) return 1@tornado.web.asynchronous @tornado.gen.engine #同步处理,不能及时响应 #@tornado.gen.coroutine 支持异步处理 def post(self): res = yield self.my_func() self.write(str(res)) self.finish()def callback(): print("start web server process")# 主函数 def main(): tornado.options.parse_command_line() # 定义app app = tornado.web.Application( handlers=[(r'/test', IndexHandler)] ) http_server = tornado.httpserver.HTTPServer(app,callback()) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()if __name__ == '__main__': main()

3. 异步处理验证 连续发送请求两次,判断下该服务是否异步处理请求。如果是单步处理,则两条请求返回时间应该相差10s。如图所示,两条请求是几乎同时处理完成的,说明异步处理成功。
Python Tornado 异步处理实现
文章图片

【Python Tornado 异步处理实现】最好在Python2.7以上安装Tornado,Python2.7以下需要安装一些依赖包,相关参考链接如下:
【1】Tornado API
【2】关于tornado.3.*的backports.ssl_match_hostname 问题
【3】Tornado 官方

    推荐阅读