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

Docker部署Python应用:Celery长任务优雅关闭方案求助

解决Docker中Celery Worker优雅关闭问题

我的Python应用运行在Docker容器中,基于Celery处理长时运行任务,但新部署时子Worker会被直接终止,无法收到安全关闭信号,导致任务中断。相关代码如下:

import time

from celery import Celery
from celery.signals import worker_ready
import logging

log = logging.getLogger()

app = Celery(
    "background_tasks",
    broker="redis://localhost:6379/0",
    backend="redis://localhost:6379/0",
)


@worker_ready.connect
def at_start(sender, **kwargs):
    log.info("Worker ready")
    with sender.app.connection() as connection:
        sender.app.send_task(daily_orders_import.name, connection=connection)


@app.task(acks_late=True)
def daily_orders_import():
    for u in range(1, 100):
        import_orders_from_account.delay(u)


@app.task(bind=True, acks_late=True)
def import_orders_from_account(self, u):
    while True:
        log.info(self.request)
        log.info(f"Importing orders for account {u}")
        time.sleep(5)

核心解决方案步骤

1. 确保Celery Worker接收终止信号

Docker默认执行docker stop时会发送SIGTERM信号给容器主进程,但如果Worker不是以PID 1运行,会无法接收信号:

  • 直接用celery命令作为容器的CMD/ENTRYPOINT,避免用未加exec的shell脚本包装。示例启动命令:
    celery -A background_tasks worker --loglevel=info --soft-time-limit=300 --time-limit=360
    
  • 若必须用脚本,用exec celery ...启动Worker,让其接管PID 1。

2. 配置Celery优雅关闭参数

启动Worker时添加关键参数:

  • --soft-time-limit=300:给运行中任务设置软超时,到达后Celery发送终止信号,任务可自行处理退出逻辑。
  • --time-limit=360:硬超时时间,作为最后保障,超时后直接终止进程。
  • --concurrency=N:根据容器资源调整并发数,确保每个Worker进程能正确处理信号。

3. 修改任务代码支持优雅终止

当前任务是无限循环且未检查终止信号,需加入Celery内置的self.request.should_stop判断:

@app.task(bind=True, acks_late=True)
def import_orders_from_account(self, u):
    while True:
        # 检查终止信号,收到则优雅退出
        if self.request.should_stop:
            log.info(f"Received stop signal, terminating import for account {u}")
            break
        log.info(self.request)
        log.info(f"Importing orders for account {u}")
        time.sleep(5)

已配置的acks_late=True会确保任务执行完成后才确认,终止时未完成的任务会被重新调度。

4. Docker层面配置优雅关闭

在docker-compose.yml或Dockerfile中明确配置:

services:
  celery-worker:
    build: .
    command: celery -A background_tasks worker --loglevel=info --soft-time-limit=300 --time-limit=360
    stopsignal: SIGTERM
    stop_grace_period: 300s
    depends_on:
      - redis
  • stopsignal: SIGTERM:显式指定发送的终止信号(默认即为SIGTERM,可强化配置)。
  • stop_grace_period: 300s:设置Docker等待进程优雅关闭的超时时间,超时后发送SIGKILL强制终止。

5. 验证流程

执行docker stop <container-name>,查看Worker日志,应能看到任务收到终止信号并主动退出,而非被直接Kill。

内容的提问来源于stack exchange,提问作者vladtamas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 05:15:14