【问题标题】:Performing a blocking request in django view在 django 视图中执行阻塞请求
【发布时间】:2026-02-12 03:20:06
【问题描述】:

在我的 django 应用程序的一个视图中,我需要执行一个相对冗长的网络 IO 操作。问题是其他请求必须等待这个请求完成,即使它们与它无关。 我做了一些研究并偶然发现了 Celery,但据我所知,它用于执行独立于请求的后台任务。 (所以我不能使用任务的结果来响应请求)

有没有办法在 django 中异步处理视图,以便在网络请求待处理时可以处理其他请求?

编辑:我忘了提到的是我的应用程序是一个使用 django rest 框架的 Web 服务。所以视图的结果是一个 json 响应,而不是我以后可以使用 AJAX 修改的页面。

【问题讨论】:

  • @Louis 抱歉,我不够清楚。参考编辑。
  • 解决方法还是一样。
  • 请详细说明您的堆栈...您使用的是 uwsgi、gunicorn 还是只是 manage.py runserver
  • @TimTisdall 相对较长,我的意思是大约 2 秒。虽然不多,但是当每个请求都阻塞了这么长的时间时,它会很快加起来。感谢您的其他评论,我一定会检查 uwsgi。

标签: python django celery


【解决方案1】:

这里通常的解决方案是将任务卸载到 celery,并在您的视图中返回“请稍候”响应。如果需要,您可以使用 Ajax 调用定期点击一个视图,该视图将报告响应是否准备好,并在准备好时重定向。

【讨论】:

  • 我忘了说的是我的应用程序是一个使用 django rest 框架的 web 服务。所以视图的结果是一个 json 响应,而不是我以后可以使用 javascript 修改的页面。
  • @alimostafavi 可以让一个 REST 调用启动流程并返回任务 ID,然后有不同的请求请求该任务的结果并返回最终结果或“还没准备好”。
【解决方案2】:

您希望长时间保持该 HTTP 连接,但仍允许管理其他请求,对吗?这个问题没有简单的解决方案。此外,任何解决方案都将与 Django 相差一个级别,因为这取决于您处理请求的方式。

我不知道你目前在用什么,所以我只能告诉你我过去是如何处理的......我使用 uwsgi 来提供我的 python 应用程序和 nginx 之间的 WSGI 接口。在 uwsgi 中,当有时间等待 IO 连接时,我使用了asynchronous functions 来暂停我的长时间运行的连接。这些方法允许你要求它暂停一些东西,直到有东西要读或写,然后允许其他连接被服务。

上述异步调用使用“绿色线程”。它比普通线程轻得多,并且您可以控制何时从一个线程移动到另一个线程。

【讨论】:

    【解决方案3】:

    我并不是说它对您的场景[1] 来说是一个很好的解决方案,但简单的答案是使用以下模式:

    async_result = some_task.delay(arg1)
    result = async_result.get()
    

    检查get method 的文档。除了使用 delay 方法,您还可以使用任何返回 AsyncResult 的方法(例如 apply_async method


    [1] 为什么这可能是个坏主意?有一个持续的连接等待很多对 Django 不利(它还没有为长期连接做好准备),可能与代理配置冲突(如果某处有反向代理)并且可能被识别为浏览器超时。所以... 将这种模式用于 Django Rest Framework 视图似乎是个坏主意。

    【讨论】:

    • 这与仅仅执行阻塞请求有何不同?无论如何都不会 get() 阻塞?
    • 如果工人不在,get() 应该释放 GIL。这意味着 Python 代码应该是畅通的。您不能释放连接并期望从 Django 回答它,但您可以“外包”任务并在解释器处理其他事情时耐心等待它。
    • @alimostafavi 但是,不要使用runserver 来真正检查行为。它永远不应该在生产中使用,它还没有准备好处理任何严重的事情。您应该使用 uwsgi、gunicorn 之类的东西...然后您可以检查您是否真的需要使用某种模式。