这类问题我又碰上了一次。Celery 5.3 配了 max_retries 三次,失败任务进重试队列后再没被消费,队列长度从两百涨到四千,worker 日志里没有新任务。

第一反应是「broker 的可见性超时太短」,验证下来不成立。

原因不止一个,得分开看。重试队列没配消费者 只监听了默认队列;acks_late 与重试组合把消息预取占住;死信没有告警 堆积到几万才发现。

上来先看各队列长度与消费者

rabbitmqctl list_queues name messages consumers

为重试队列单独起一个 worker

celery -A app worker -Q retry -c 4

调整可见性超时与预取数

celery -A app worker --prefetch-multiplier 1

给死信队列加阈值告警

python alert.py --queue retry --threshold 500

同事提醒我看一下最近一次发布,时间点确实对得上。

命令输出我都留了记录,免得改完记不清原来的值。

恢复的判定其实很直接。重试队列长度回落到两位数,失败任务都能被重新消费,告警可在堆积前触发。

这里还有个坑。重试队列也是队列,没有消费者就是黑洞,配路由时要一并配 worker。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。

作者 9823189