python - 如何使用 python tornado @gen.coroutine 和长时间运行的函数
问题描述
我有一个 Web 应用程序,它也在进行非常密集的数据处理。有些功能非常慢(想想几分钟)。
到现在为止,我的架构是为每个连接生成新的线程/进程,因此这些慢速功能不会阻塞其他用户。但这会消耗太多内存,并且不利于龙卷风架构。
所以我想知道这种问题是否有解决方案。我的代码如下所示:
# code that is using to much memory because of the new threads being spawned
def handler():
thread = Thread(target = really_slow_function)
thread.start()
thread.join()
return "done"
def really_slow_function():
# this is an example of an intensive function
# which should be treated as a blackbox
sleep(100)
return "done"
重构后,我有以下代码:
#code that doesn't scale because all the requests are block on that one slow request.
@gen.coroutine
def handler():
yield really_slow_function()
raise gen.Return("done")
def really_slow_function():
# this is an example of an intensive function
# which should be treated as a blackbox
sleep(100)
return "done"
此重构的问题在于,tornado 服务器阻塞了really_slow_function
并且同时无法为其他请求提供服务。
所以问题是:有没有一种方法可以在不触及really_slow_function
和不创建新线程/进程的情况下重构处理程序?
解决方案
使用ThreadPoolExecutor
(来自concurrent.futures
包)在单独的线程中运行长时间运行的函数,而无需每次都启动一个新线程。
async def handler():
await IOLoop.current().run_in_executor(None, really_slow_function)
return "done"
如果你想准确控制有多少线程有资格运行这个函数,你可以创建自己的执行器并传递它而不是None
.
推荐阅读
- spring-webflux - 在 Spring WebFlux Web 应用程序中缓存来自 WebClient 调用的 Mono 结果
- .net-core - 我可以缩小 dotnet 发布包吗
- c - 从核心转储中获取被调用函数的返回值
- jquery - 带有两个模态的两个视频
- javascript - EXCEL VBA HTML 单击按钮,然后单击下拉选项
- freepascal - TFPCustomHashTable 构造函数使用 196613 常量。为什么要使用这个特定的值?
- asp.net-mvc - MVC 5 ActionResult 参数始终为空
- angular - 如何在 ngxs 中订阅元选择器(组合状态选择器)?
- c - 为什么我的右移运算符在逻辑上而不是在 c 中以算术方式运行?
- amazon-web-services - Amazon 为 EKS VPC 设置建议的 Cloudformation 模板直接与其建议相矛盾。是否存在其他模板?