我最近一直在使用烧瓶在 python 中做一个宠物项目。它是一个简单的 pastebin,带有 pygments 的服务器端语法高亮支持。因为这是一项代价高昂的任务,所以我将语法突出显示委托给 celery 任务队列,并在请求处理程序中等待它完成。不用说,这只不过是减轻了另一个工作人员的 CPU 使用率,因为等待结果仍然会锁定与 Web 服务器的连接。尽管我的直觉告诉我要避免像瘟疫那样过早的优化,但我仍然忍不住研究异步。
异步
如果最近一直在关注 Python Web 开发,那么您肯定已经看到异步无处不在。async 所做的是带回协作多任务,这意味着每个“线程”决定何时何地让步给另一个。这种非抢占式进程比操作系统线程更有效,但仍然有它的缺点。目前似乎有两种主要方法:
- 事件/回调风格的多任务处理
- 协程
第一个通过在事件循环中执行的松散耦合组件提供并发性。尽管这在竞争条件方面更安全并提供了更高的一致性,但与抢先式多任务处理相比,它的直观性和编码难度要小得多。
另一种是更传统的解决方案,更接近线程编程风格,程序员只需手动切换上下文。虽然更容易出现竞争条件和死锁,但它提供了一个简单的解决方案。
目前大多数异步工作都是在所谓的IO-bound任务上完成的,即阻塞等待输入或输出的任务。这通常是通过使用可以调用的轮询和基于超时的函数来完成的,如果它们返回负数,则可以切换上下文。
尽管有这个名字,但这也可以应用于CPU 密集型任务,可以委托给另一个工作人员(线程、进程等),然后非阻塞地等待屈服。理想情况下,这些任务将以异步友好的方式编写,但实际上这意味着将代码分成足够小的块以防止阻塞,最好不要在每一行代码之后分散上下文切换。这对于现有的同步库来说尤其不方便。
由于方便,我决定使用 gevent 进行异步工作,并想知道如何在异步环境中处理 CPU 密集型任务(使用期货、芹菜等?)。
如何将异步执行模型(在本例中为 gevent)与烧瓶等传统 Web 框架一起使用?python(期货,任务队列)中这些问题的一些普遍同意的解决方案是什么?
编辑:更具体地说 - 如何在烧瓶中使用 gevent 以及如何在这种情况下处理 CPU 密集型任务?
EDIT2:考虑到 Python 如何具有阻止线程代码最佳执行的 GIL,至少在我的情况下,这只留下了多处理选项。这意味着要么使用concurrent.futures ,要么使用其他一些处理处理的外部服务(甚至可以为与语言无关的东西打开大门)。在这种情况下,gevent(即芹菜)的一些流行或经常使用的解决方案是什么?- 最佳实践