Celery Worker容器触发MemoryError后无法自动重启求助
问题诊断与解决方案
核心问题分析
- Docker重启策略生效条件:你配置的
deploy.restart_policy仅在Docker Swarm集群模式下生效,若使用普通docker-compose up启动容器,该配置完全无效——这是最可能导致容器不重启的原因。 - Celery进程退出码异常:Python抛出
MemoryError后,Celery可能以退出码0终止进程(部分版本中未正确将不可恢复错误映射为非0退出码),而Docker的on-failure策略仅在容器退出码非0时触发重启。 - 内存控制策略未精准适配:
worker_max_tasks_per_child=1000仅限制任务数,若单个任务占用内存过大,会在任务数未达标时就耗尽内存。
分步解决方案
1. 修正Docker Compose重启配置(优先处理)
将Swarm专用的deploy.restart_policy替换为普通Compose生效的顶层restart字段:
worker: build: . env_file: - .env command: celery -A my_app worker --loglevel=info --concurrency 1 -E # 替换原deploy.restart_policy,普通docker-compose启动时生效 restart: on-failure:3 depends_on: - api # 可选:配置内存限制,触发Docker OOM Killer时强制非0退出 resources: limits: memory: 512M reservations: memory: 256M
若你确实使用Swarm集群,则保留deploy.restart_policy,但需验证Celery进程的退出码。
2. 强制Celery非0退出
若Celery因MemoryError退出时返回码为0,可通过shell脚本包裹启动命令,确保进程异常时返回非0码:
command: sh -c 'celery -A my_app worker --loglevel=info --concurrency 1 -E || exit 1'
3. 优化Celery内存管理
- 降低单worker的任务上限:将
worker_max_tasks_per_child调整为更小值(如100),减少内存累积时间:# 在Celery配置文件中添加 worker_max_tasks_per_child = 100 - 新增内存阈值限制:设置
worker_max_memory_per_child,当worker内存超过阈值时自动重启子进程(单位为KB,示例为50MB):worker_max_memory_per_child = 50000 - 排查单个任务的内存泄漏:检查任务中是否存在未释放的大对象、未关闭的数据库连接/文件句柄、全局缓存未清理等问题。
4. 验证退出码
手动触发MemoryError后,查看容器退出码确认是否为非0:
# 查看最近退出的worker容器退出码 docker inspect <worker-container-id> | grep ExitCode
若返回"ExitCode": 0,则需通过步骤2的shell脚本强制非0退出。
内容的提问来源于stack exchange,提问作者SylvainB
相关产品推荐
相关产品推荐

