美文网首页
tornado异步非阻塞请求

tornado异步非阻塞请求

作者: 来一碗花甲粉 | 来源:发表于2019-04-09 17:26 被阅读0次

    基础知识

    首先对同步/异步、阻塞/非阻塞、以及tornado中asyncio进行了解,参考下面的文章
    1.python中的异步实践与tornado应用
    https://my.oschina.net/yangyanxing/blog/3001436
    2.关于 asyncio
    https://binglau7.github.io/2018/01/30/%E5%85%B3%E4%BA%8E-asyncio-%E7%9A%84%E5%96%83%E5%96%83%E8%87%AA%E8%AF%AD/

    注意

    程序中的数据库读取等io操作都要改为异步的,才能真正实现异步性能,否则还是会阻塞请求

    实践

    1. 因为项目中历史问题,让前端统一接口调用方式,在新tornado后端服务中,采用了异步转发
      使用
      python3.7 中 async/await
      tornado 5.1 中 tornado.httpclient.AsyncHTTPClient()
      //tornado.gen.Task 方法在5.1版本以后弃用
    from .base.base_handler import BaseHandler
    import tornado.web
    import tornado.gen
    import tornado.httpclient
    from tornado.options import options
    import time
    import asyncio
    
    class RedirectHandler(BaseHandler):
       async def post(self):
           method = self.get_argument('method')
           modular = self.get_argument('modular')
           headers = self.request.headers
           body = self.request.body
           http_client = tornado.httpclient.AsyncHTTPClient()
           url = 'http://localhost:{0}/{1}/{2}'.format(options.port, modular, method)
           resp = await http_client.fetch(
               url,
               method="POST", 
               headers=headers,
               body=body, 
               validate_cert=False
           )
           #响应的headers
           #print(resp.headers)
           self._headers = resp.headers
           self.write(resp.body)
    
    1. 多线程使用
      项目中需要导出表格,比较耗时,使用异步多线程
      使用
      python3.7 中 ThreadPoolExecutor
      tornado 5.1 +
      @tornado.gen.coroutine
      @run_on_executor
    import tornado.web
    import tornado.gen
    from tornado.ioloop import IOLoop
    from tornado.concurrent import run_on_executor
    from concurrent.futures import ThreadPoolExecutor
    
    from .base.base_handler import BaseHandler
    from utils.json_encoder import convert2json, error2json
    from constants import *
    from service.export_deliver.dispatch_center import ExportDeliverDispatch
    from utils.time_convert import timestamp_to_datetime
    
    class ExportDeliverHandler(BaseHandler):
        executor = ThreadPoolExecutor(10) #  线程池
    
        #@tornado.web.asynchronous
        @tornado.gen.coroutine
        def post(self):
            params = self.request.body
            params = json.loads(params)
            temp_id = params.get('tempId', '')
            dataset_col = params.get('dataset').get('colName')
    
            filename, stream = yield self.deliver(params)
            #Content-Type这里我写的时候是固定的了,也可以根据实际情况传值进来
            self.set_header('Content-Type', 'application/octet-stream')
            # 中文文件名用quote解决
            self.set_header('Content-Disposition', "attachment; filename={0}".format(quote(filename)))
            #读取的模式需要根据实际情况进行修改
            self.write(stream)
    
        @run_on_executor
        def deliver(self, params):
           # dosomething
            return filename, stream
    

    可用遇到报错信息:
    RuntimeError: There is no current event loop in thread ThreadPoolExecutor-xxx
    解决:
    线程中执行代码的开始,加上下面代码(在2.关于 asyncio中也有介绍)

    new_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(new_loop)
    

    相关文章

      网友评论

          本文标题:tornado异步非阻塞请求

          本文链接:https://www.haomeiwen.com/subject/gynuiqtx.html