队列里堆了两千条小任务,八个 worker 只有两个在干活,其余六个空转,监控显示它们手里的预取额度都压在一条慢任务后面。碰到这种情况,我一般先确认改动有没有真的生效。
原因不复杂,默认每个 worker 预取并发数四倍的消息,取走就锁在自己手里,前面一条慢任务没结束,后面的小任务只能跟着排队干等,别的 worker 想帮也帮不上。
「Celery 预取配置」相关的日志我一般连着看前后五分钟,单看一条报错经常判断不出是哪一步失败。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
celery -A proj worker -c 8 --prefetch-multiplier=1 # 或写进配置 app.conf.worker_prefetch_multiplier = 1
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。
具体做法是,把预取倍数调成一,让空闲的 worker 能立刻拿到新任务;配合延迟确认,任务失败时消息能重新回到队列里重投;按任务耗时拆成两个队列,慢任务单独给一组 worker,互不干扰。
最后用这个标准收尾,空闲的 worker 明显减少,队列堆积在几分钟内被消化,延迟也降下来。
