Python分布式任务队列Celery经常卡死,如何排查和解决?

celery worker 经常卡死,例如 并发数 是 4,然后经常就有 4 个任务状态卡在 started 或者 received 不动,然后也不会抛出异常。我是设置了超时的 CELERYD_TASK_SOFT_TIME_LIMIT = 120

但是时间过了很久 也不会抛出 异常 SoftTimeLimitExceeded

我看文档是肯定会抛出的。但是这个有的时候能抛出,有的时候不会抛出,然后就卡死在那个地方! 整了一周了还是没找到问题


Python分布式任务队列Celery经常卡死,如何排查和解决?

12 回复

什么版本
某些版本有这样的问题


Celery卡死通常有几个常见原因,排查时可以按这个顺序来:

  1. 检查Broker连接:最常见的就是RabbitMQ或Redis连接断了。用celery -A proj inspect ping测试worker是否存活,再检查broker服务状态和网络。

  2. 看日志:启动worker时加-l INFO-l DEBUG,卡住时通常会有超时或连接错误。重点看是不是有任务hang住了。

  3. 任务死锁:有些任务可能卡在I/O、外部API调用或数据库长事务里。给任务设soft_time_limittime_limit,比如:

@app.task(soft_time_limit=60, time_limit=120)
def my_task():
    # 任务逻辑

超时的任务会被中断。

  1. 资源泄漏:检查内存是否爆了。可以用flower监控,或者用--maxtasksperchild参数让worker定期重启释放资源。

  2. 预取数太多:默认prefetch multiplier是4,如果任务长,worker可能卡在等待。启动时加-O fair禁用预取,或者设worker_prefetch_multiplier = 1

  3. 数据库连接:如果用了django-celery,数据库连接可能没关。确保每个任务结束后正确关闭db连接。

简单说就是先ping,再看日志,加超时,调参数。

用的 redis ?

celery 的确会这样,内存占用会越来越多,然后就假死,建议写个检测脚本定时重启。
或者找一个替代品例如这个: https://github.com/Bogdanp/dramatiq

rabbitmq

如果用检测脚本定时重启的话,请问怎么检测到是否假死呢?

之前做的是每隔一段时间就检测 celery 所有进程内存占用,到一定量时不管假不假死都重启。你可以根据是否有日志输出来重启。
实际我还是建议你换这个 https://github.com/Bogdanp/dramatiq,celery 我一直怀疑它内存泄漏。

感谢

用的 4.2.0

try 4.1 或者 3.1

我也是。。我头都大了。。任何异常不抛出,同时使用 beat 和 worker,会发现 beat 很好,worker 会过几天突然莫名其妙的不执行了,Received task 都没有了,但是开了 Debug 模式,没有任何异常报告。

实在不成打算用 RQ 了。不好的地方就是首先要重新学习,其次 RQ 没有原生支持类似 beat 这样的计划任务模块,但有扩展包,别人写了一个。

回到顶部