运行 Django 网络应用程序中的异步 python 代码

Running asynchronous python code in a Django web application

是否可以在 Django 网络应用程序中异步 运行 某些代码片段。如果有怎么办?

例如:

我有一个搜索算法可以 returns 成百上千个结果。我想将这些项目是搜索结果输入到数据库中,这样我就可以看到用户搜索最多的是什么。我不希望客户端不得不等待额外的一百或一千个数据库插入。有没有办法异步执行此操作?这样做有什么危险吗?有没有更好的方法来实现这个?

就 Django 而言是的。

更大的问题是您的 Web 服务器以及它是否适合线程处理。比如gunicorn的sync worker是单线程的,但是也有其他引擎,比如greenlet。我不确定他们玩线程的效果如何。

如果您从线程中分叉,则结合线程和多处理可能会成为一个问题:

Status of mixing multiprocessing and threading in Python

http://bugs.python.org/issue6721

也就是说,我知道流行的性能分析实用程序一直在使用线程来报告指标,所以这似乎是一种公认​​的做法。

总之,使用标准库中的 threading.Thread 对象似乎是最安全的,只要您在其中所做的任何事情都不会分叉(python 的多处理库)

https://docs.python.org/2/library/threading.html

从主线程卸载请求是一种常见的做法;因为最终目标是 return 尽快向客户端(浏览器)发送结果。

我相信您知道,HTTP 是阻塞的 - 所以在您 return 响应之前,客户端无法执行任何操作(它被阻塞,处于等待状态)。

卸载请求的实际方法是通过 celery,这是一个任务队列系统。

我强烈建议您阅读 introduction to celery 主题,但总结如下:

  1. 您将某些代码段标记为"tasks"。这些通常是您想要异步 运行 的函数。

  2. Celery 管理 worker - 您可以将它们视为线程 - 这将 运行 这些任务。

  3. 要与工作人员通信,需要 消息队列RabbitMQ 是经常推荐的。

一旦您拥有所有组件 运行ning(只需要几分钟);你的工作流程是这样的:

  1. 在您看来,当您想卸载一些工作时;您将调用与 .delay() 选项一起工作的函数。这将触发worker开始在后台执行方法。

  2. 您的观点 return 立即回复。

  3. 然后您可以检查任务的结果,并根据需要执行的操作采取适当的操作。还有ways to track progress

包含缓存也是一种很好的做法 - 这样您就不会执行不必​​要的昂贵任务。例如,您可以选择卸载对将放置在报告中的搜索关键字进行一些分析的请求。

生成报告后,我会缓存结果(如果适用),以便以后请求时可以显示相同的报告 - 而不是再次生成。