【问题标题】:Django concurrency with celeryDjango 与 celery 并发
【发布时间】:2016-03-04 17:16:47
【问题描述】:

我正在使用 django 框架并遇到了一些性能问题。

在我的views.py中有一个非常重的(大约需要2秒)。我们称之为heavy()

客户端使用ajax发送请求,路由到heavy(),等待json响应。

不好的是,我认为heavy() 不是并发的。如下图所示,如果有两个请求同时路由到heavy(),则必须等待另一个。换句话说,heavy() 是串行的:在从当前请求返回之前,它不能接受另一个请求。该观察结果在我的本地机器上进行了测试和验证。

我正在尝试制作views.pyconcurrentasynchronous 中的函数。理想情况下,当有两个请求到达heavy() 时,heavy() 应该通过回调将作业丢给远程工作人员,然后返回。然后,heavy() 可以处理另一个请求。任务完成后,回调可以将结果发送回客户端。逻辑如下:

但是有一个问题:如果heavy()要处理另一个请求,它必须返回;但如果它返回一些东西,django 框架会向客户端发送一个(假)响应,而客户端可能不会等待另一个响应。此外,虚假响应不包含正确的数据。我已经搜索了 stackoverflow 并找到了不太有用的提示。我想知道是否有人尝试过这个并且知道解决这个问题的好方法。

谢谢,

【问题讨论】:

  • 您使用的是什么服务器? Django 开发服务器?

标签: django multithreading asynchronous concurrency celery


【解决方案1】:

跟进 GwynBliedD 的回答:

celery 常用来处理任务,它有非常简单的 django 集成。 @GwynBlieD 的第一个建议通常使用 celery 和 celery 结果后端来实现。

https://www.reddit.com/r/django/comments/1wx587/how_do_i_return_the_result_of_a_celery_task_to/

使用 celery 的常见工作流程是:

  1. client hits heavy()
  2. heavy() 异步将 Heavy() 任务排队
  3. heavy() 将未来的任务 ID 返回给客户端(视图返回非常快,因为实际执行的工作很少)
  4. 客户端开始使用任务 ID 轮询状态端点
  5. 当任务完成状态返回结果给客户端

【讨论】:

    【解决方案2】:

    首先确保“不并发”实际上是由您的繁重任务引起的。如果您只为 django 使用一名工作人员,那么您一次只能处理一个请求,无论它是什么。考虑为某些并发设置更多工作人员,因为它也会影响短请求。

    要在任务完成时返回一些信息,您至少可以通过两种方式进行:

    • 定期发送 AJAX 请求以获取任务状态
    • 使用 SSE 或 websocket 订阅实际结果

    他们都需要编写更多的 JavaScript 代码来处理它。第一个非常容易实现,第二个可以使用 uWSGI 功能,如here 所述。它可以通过这种方式异步处理,独立于您的 django 工作人员(django 只会在 celery 中创建连接并启动任务,检查状态并将其发送到客户端将由 gevent 处理。

    【讨论】:

    • 我自己使用轮询。您链接到的那篇文章对于希望使用 Django 使用 websocket 的人来说是必读的。
    猜你喜欢
    • 1970-01-01
    • 2013-09-18
    • 2017-10-24
    • 2011-06-15
    • 2012-04-14
    • 1970-01-01
    • 2019-11-15
    • 2021-08-18
    • 1970-01-01
    相关资源
    最近更新 更多