Supervisor托管Docker环境中Celery每2分钟无日志重启问题咨询
结合你描述的“Celery固定2分钟周期重启、应用日志无相关报错”的特征,按出现概率从高到低的诱因和对应处理方案如下:
1. 进程被内核OOM Killer静默终止
诱因:Celery worker长期运行存在内存泄漏,内存占用达到RHEL宿主机的内存阈值时,会被内核直接发送SIGKILL强制终止。这类终止不会在Celery应用日志、Supervisor的stderr日志中留下应用层报错,而Supervisor检测到进程退出后自动拉起,重启周期刚好和内核OOM检测、内存回收的周期(约2分钟)匹配。
对应方案:
- 在RHEL宿主机执行命令
dmesg -T | grep -i "oom\|killed process",排查是否存在celery进程被OOM终止的记录 - 在Celery启动命令中增加内存自动回收参数,避免内存长期累积泄漏:
celery -A CELERY_APP worker --loglevel=info --logfile=/var/log/supervisor/celery.log --max-tasks-per-child=100 --max-memory-per-child=200000(--max-memory-per-child单位为KB) - 在docker-compose配置中为应用容器增加内存限制
mem_limit: 2g,避免单个容器占满宿主机内存触发全局OOM。
2. Celery与RabbitMQ心跳超时触发进程被动退出
诱因:默认Celery版本的MQ心跳间隔为30秒,如果Docker网络存在间歇性丢包、RHEL默认firewalld规则对网桥流量设置了短连接超时,导致连续3次心跳超时(合计90秒,接近2分钟周期),Celery worker会主动断开连接并退出。这类由信号触发的退出,在info级别的日志中不会留下明确的错误栈。
对应方案:
- 将Celery启动日志级别临时调整为debug,观察是否存在心跳超时相关的记录:把启动命令中的
--loglevel=info替换为--loglevel=debug - 在Django配置中显式固定心跳参数,避免自动判定的异常:
CELERY_BROKER_HEARTBEAT = 30 CELERY_BROKER_CONNECTION_RETRY_ON_STARTUP = True - 检查RabbitMQ容器与应用容器之间的网络连通性,通过
telnet <RabbitMQ容器IP> 5672确认连接无被firewalld重置、丢包的情况。
3. Supervisor配置的进程组信号扩散
诱因:你当前的Supervisor配置中开启了killasgroup=true,如果Celery worker和Celery beat属于同一个进程组,任意一个进程收到终止信号,会导致组内所有进程被连带杀掉。如果Celery beat因为定时任务调度、持久化文件损坏的问题每2分钟退出一次,就会连带触发同组worker的重启,从外部观测就会呈现“worker每2分钟重启、无日志记录”的特征。
对应方案:
- 首先查看Supervisor主日志
/var/log/supervisor/supervisord.log,提取进程退出时的退出码:如果退出码为137代表被SIGKILL终止,143代表被SIGTERM终止,以此判定触发来源 - 拆分两个服务的进程组设置,分别在
[program:django-celery]和[program:django-celerybeat]配置块中增加参数:stopasgroup=false killasgroup=false setugid=false - 检查Celery beat的持久化文件权限,把beat的调度文件路径固定为可读写的应用目录,避免因为schedule文件损坏触发beat进程退出,可在beat启动命令中增加前置清理逻辑:
rm -f /app/celerybeat-schedule && celery -A CELERY_APP beat ...
4. Docker容器主进程运行模式错误
诱因:你当前的Dockerfile依赖自定义的/start脚本启动Supervisor,如果脚本中是后台模式启动supervisord(即没有加-n前台运行参数),会导致Docker容器的主进程过早退出,触发Docker本身的容器重启循环,而这类重启不会在Supervisor、Celery的应用日志中留下记录。
对应方案:
- 检查
/start脚本的内容,确认Supervisor的启动命令为前台运行模式:supervisord -n -c /etc/supervisor/supervisord.conf,避免因为主进程退出触发Docker层面的容器重启
补充排查提示
如果完成上述排查仍未定位问题,可临时在RHEL宿主机上通过ps -ef | grep celery监控进程的PID变化频率,确认是Supervisor层面的进程重启,还是Docker层面的容器整体重启,进一步缩小排查范围。
内容的提问来源于stack exchange,提问作者Nithin Varghese

