【问题标题】:How do Celery run multiple tasks so slow with Python?Celery 如何使用 Python 运行多个任务这么慢?
【发布时间】:2013-06-20 23:56:49
【问题描述】:

我的芹菜以amqp开头

     -------------- celery@tty-Gazelle-Professional v3.0.19 (Chiastic Slide)
     ---- **** ----- 
     --- * ***  * -- Linux-3.8.0-25-generic-x86_64-with-Ubuntu-13.04-raring
     -- * - **** --- 
     - ** ---------- [config]
     - ** ---------- .> broker:      amqp://guest@localhost:5672//
     - ** ---------- .> app:         proj.celery:0x25ed510
     - ** ---------- .> concurrency: 8 (processes)
     - *** --- * --- .> events:      OFF (enable -E to monitor this worker)
     -- ******* ---- 
     --- ***** ----- [queues]
     -------------- .> celery:      exchange:celery(direct) binding:celery

有一个功能:

    def prime(n):
        .....
        .....
        return number_of_primes_below_n

所以我把这个函数作为 celery 中的一项任务,并与串行计算进行比较

连续剧:

    [prime(i) for i in xrange(10, 100000)]

与芹菜并列:

    from celery import *
    
    g = group(prime.s(i) for i in xrange(10, 100000))
    res = g.apply_async()

当我 apply_async() 时,在后端很快就会在终端屏幕上显示结果,例如:

[2013-06-20 16:34:56,238: INFO/MainProcess] Task proj.tasks.do_work[989be06b-c4f3-4876-9311-2f5f813857d5] succeeded in 0.0166230201721s: 99640324
[2013-06-20 16:34:56,241: INFO/MainProcess] Task proj.tasks.do_work[6eaa9b85-7ba2-4397-b6ae-cbb5668633d4] succeeded in 0.0123620033264s: 99740169
[2013-06-20 16:34:56,242: INFO/MainProcess] Task proj.tasks.do_work[1f5f6302-94a3-4937-9914-14690d856a5d] succeeded in 0.00850105285645s: 99780121
[2013-06-20 16:34:56,244: INFO/MainProcess] Task proj.tasks.do_work[b3735842-a49c-48a3-8a9e-fab24c0a6c23] succeeded in 0.0102620124817s: 99820081
[2013-06-20 16:34:56,245: INFO/MainProcess] Task proj.tasks.do_work[98eec31a-52eb-4752-92af-6956c0e6f130] succeeded in 0.00973200798035s: 99880036
[2013-06-20 16:34:56,245: INFO/MainProcess] Task proj.tasks.do_work[011a1e99-b307-480b-9765-b1a472dbfa8c] succeeded in 0.0115168094635s: 99800100
[2013-06-20 16:34:56,245: INFO/MainProcess] Task proj.tasks.do_work[f3e3a89f-de79-4ab0-aab7-0a71fe2ab2f7] succeeded in 0.010409116745s: 99840064
[2013-06-20 16:34:56,246: INFO/MainProcess] Task proj.tasks.do_work[61baef04-03c2-4810-bf6a-ae7aa75b80b4] succeeded in 0.0112910270691s: 99860049

但是当我想用 celery 得到结果时

    res.get()

它运行非常非常慢,比串行慢得多。问题是什么?是不是因为 celery group 的结果比较慢?我该如何解决这个问题?

【问题讨论】:

  • 如果您需要更快的速度,只需添加更多的工人。工人也可以在其他机器上运行。这就是使用 AMQP 的全部意义所在,如果您不允许在问题上扔硬件,那么 celery 可能是矫枉过正。
  • @PauloScardine 非常感谢 Paulo,正如您从顶部看到的那样,并发:8(进程),我可以添加 8 个工人来做 group() 吗?谢谢
  • 如果它是 CPU 密集型的,那么运行比核心数量更多的工作线程是没有意义的 - 如果你有其他机器空闲,使用它们,在其他主机上使用真实 IP 地址AMQP 服务器而不是 localhost(不要在每台机器上运行一个 AMQP 服务器,将所有机器指向同一个服务器)。如果它是 I/O 密集型的,请在 I/O 等待低于 1 或 2(vmstat 10 10 的最后一列)时继续提高它。
  • @PauloScardine 我又添加了两个工人,实际上每个工人都计算自己的部分,这意味着它并行运行,并且在后端我可以看到打印的结果。但是,当我执行 res.ready() 或 res.get() 时,它总是挂在那里,但我确信所有工作人员都完成了他们的工作。
  • 对于较大的结果,在队列中维护状态可能会很昂贵,您可以尝试将其存储在数据库中。

标签: python celery


【解决方案1】:

如果你对 res.get() 操作计时,你会注意到(我希望这是真的),那总是大约 500 毫秒。这是因为 AsyncResult.get 必须每 N 毫秒轮询一次结果。您可以通过为 get 提供额外的参数来调整它,interval

res.get(interval=0.005)  

您可以通过in documentationsource 获取更多信息。请注意,Celery 不是类 RPC 通信的最佳解决方案,因为轮询结果会导致很大的性能损失。

My own question

【讨论】:

  • 请注意,即将推出的 Celery 3.1 中有一个新的 'rpc' 后端对此进行了优化:)
  • 即是非持久化的,只有发起任务的进程才能取回结果(request-reply pattern)
  • @asksol,谢谢。你能给出一些链接/示例这个“rpc”后端是如何工作的吗?我没有在文档中找到任何内容。
  • 对于文档中不容易找到的问题,这是一个很好的答案。
猜你喜欢
  • 1970-01-01
  • 2016-07-20
  • 2011-09-15
  • 1970-01-01
  • 2020-08-10
  • 2018-11-13
  • 2021-02-05
  • 2021-04-26
  • 1970-01-01
相关资源
最近更新 更多