worker 连续跑 5 天后 RSS 从 320MB 涨到 2.1GB,第 6 天被 OOM killer 杀掉,dmesg 里留下 Out of memory: Killed process。乍看像缓存或者权限的锅,追下去往往不是。

celery -A app worker --max-tasks-per-child=200 -c 4
ps -o rss= -p $(pgrep -f 'celery.*worker' | head -1)

追下去是这么回事:每个任务都会加载一次图像处理库,句柄和缓存挂在模块级变量上,任务结束不释放。worker 进程长期不退出,内存只增不减。

碰到「worker 内存泄漏」这类问题,我习惯先把当前配置原样备份一份,改坏了立刻换回来,不用现场推。接口问题先分清是没发出去、发出去了没收到,还是收到了处理失败。

偶发问题先统计频率,一小时几次和一天一次,查法完全不同。改完顺手把文档补一句,省得下次自己重新推一遍。

监控和日志的时间要对上,时区不一致会多绕很大一圈。

具体做法是,开启 max_tasks_per_child 处理 200 个任务后重启子进程;把模块级缓存换成带容量上限的 LRU;用 memory_profiler 跑一批任务 确认增长点在哪一行;持续观察一周 RSS 曲线 确认是锯齿波动而不是单调上涨。

验收就看一点,跑 2000 个任务后 RSS 稳定在 400MB 上下 随子进程重启呈锯齿波动 不再单调上升。

作者 9823189