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