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 )
1 neoblackcap 2020-09-28 23:45:05 +08:00 你同步 IO 的操作,那么就放在线程池 /进程池里面跑,跑完返回结果就可以了。标准库里面是有相关的辅助函数的,你去看看 asyncio 里面的文档。 tornado 是兼容 asyncio 的,你直接用就好了 |
2 vhysug01 OP @neoblackcap 好的,我去翻翻文档 |
![]() | 3 shuax 2020-09-29 09:25:19 +08:00 run_in_executor |
![]() | 4 ruanimal 2020-09-29 10:10:21 +08:00 你得保证你用的 es 库是支持异步才行 |
5 xulolololololo 2020-09-29 12:25:43 +08:00 via Android 你都用异步协程框架了,还用同步的 client,想啥呢,es,mysql, redis 都有异步的库装了用起来就完事 |
6 vhysug01 OP @xulolololololo 内网,不能新装包,领导不同意,感觉用 tornado 卵用没有,一点特性用不上 |
7 LukeChien 2020-09-29 13:07:18 +08:00 via Android handler 里面 yield 挂起,等待线程池里的 es 客户端返回,不影响其他请求的处理 参考文章: https://www.cnblogs.com/terencezhou/p/7615572.html |
10 xulolololololo 2020-09-29 19:33:08 +08:00 via Android 建议换公司 |
11 vhysug01 OP @xulolololololo 暴力解决法 |