V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
vhysug01
V2EX  ›  Python

tornado 异步非阻塞求解救

  •  
  •   vhysug01 · 2020-09-28 22:39:50 +08:00 · 1943 次点击
    这是一个创建于 1536 天前的主题,其中的信息可能已经有所发展或是发生改变。
    
    class Handler:
    
    	def get(self):
    		res_a = self.get_a(*args)
    		res_b = self.get_b(*args)  # => cost 1s
    		self.write({"res": res_a + res_b})
    
    	def get_a(self, *args):
    		res = {}
    		a1 = self.get_a1(*args)  # => cost 2s
    		a2 = self.get_a2(*args)  # => cost 3s
    		res.update(a1)
    		res.update(a2)
    		return res
    
    	def get_b(self, *args):
    		pass
    
    

    现在 tornado 代码是这么个流程,几个调用耗时的方法,都是 io 问题(读 es,且不可能安装异步的 es 客户端包),这种情况下,整个服务性能特别低,用 async 装饰耗时函数,但是也各种报错,没有找到解决办法。网上看 asyncio,executor 也是没有头绪,因为 get_a 方法,如果起多线程,应该可以保证 3s 就返回,而 get 函数,总共也是可以 3s 就返回的,包括异步客户端也一样。现在这么一写,多耗费了 1 倍的时间...

    所以,大佬们有什么解决方法么,或者改看哪方面知识么,求告知 😂

    以下为报错问题的代码及报错

    
    class Handler:
    
    	async def get(self):
    		res_a = await self.get_a(*args)
    		res_b = self.get_b(*args)  # => cost 1s
    		self.write({"res": res_a + res_b})
    
    	async def get_a(self, *args):
    		res = {}
    		a1 = await self.get_a1(*args)  # => cost 2s
    		a2 = self.get_a2(*args)  # => cost 3s
    		res.update(a1)
    		res.update(a2)
    		return res
    
    	async def get_a1(self):
    		res = await ...
    		return res
    
    	def get_b(self, *args):
    		pass
    
    # Error
    # object list can't be used in await expression )
    
    11 条回复    2020-09-30 09:59:24 +08:00
    neoblackcap
        1
    neoblackcap  
       2020-09-28 23:45:05 +08:00
    你同步 IO 的操作,那么就放在线程池 /进程池里面跑,跑完返回结果就可以了。标准库里面是有相关的辅助函数的,你去看看 asyncio 里面的文档。
    tornado 是兼容 asyncio 的,你直接用就好了
    vhysug01
        2
    vhysug01  
    OP
       2020-09-29 09:19:21 +08:00 via iPhone
    @neoblackcap 好的,我去翻翻文档
    shuax
        3
    shuax  
       2020-09-29 09:25:19 +08:00
    run_in_executor
    ruanimal
        4
    ruanimal  
       2020-09-29 10:10:21 +08:00
    你得保证你用的 es 库是支持异步才行
    xulolololololo
        5
    xulolololololo  
       2020-09-29 12:25:43 +08:00 via Android
    你都用异步协程框架了,还用同步的 client,想啥呢,es,mysql, redis 都有异步的库装了用起来就完事
    vhysug01
        6
    vhysug01  
    OP
       2020-09-29 12:54:54 +08:00
    @xulolololololo 内网,不能新装包,领导不同意,感觉用 tornado 卵用没有,一点特性用不上 😂
    LukeChien
        7
    LukeChien  
       2020-09-29 13:07:18 +08:00 via Android
    handler 里面 yield 挂起,等待线程池里的 es 客户端返回,不影响其他请求的处理 参考文章: https://www.cnblogs.com/terencezhou/p/7615572.html
    vhysug01
        8
    vhysug01  
    OP
       2020-09-29 13:32:58 +08:00 via iPhone
    @LukeChien 👍
    ruanimal
        9
    ruanimal  
       2020-09-29 16:53:34 +08:00
    @vhysug01 离线下载安装啊,能用库解决的问题,为啥动代码。
    xulolololololo
        10
    xulolololololo  
       2020-09-29 19:33:08 +08:00 via Android
    建议换公司
    vhysug01
        11
    vhysug01  
    OP
       2020-09-30 09:59:24 +08:00
    @xulolololololo 暴力解决法
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2210 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 16:03 · PVG 00:03 · LAX 08:03 · JFK 11:03
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.