You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Celery Worker容器触发MemoryError后无法自动重启求助

问题诊断与解决方案

核心问题分析

  1. Docker重启策略生效条件:你配置的deploy.restart_policy仅在Docker Swarm集群模式下生效,若使用普通docker-compose up启动容器,该配置完全无效——这是最可能导致容器不重启的原因。
  2. Celery进程退出码异常:Python抛出MemoryError后,Celery可能以退出码0终止进程(部分版本中未正确将不可恢复错误映射为非0退出码),而Docker的on-failure策略仅在容器退出码非0时触发重启。
  3. 内存控制策略未精准适配: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 14:05:54