Celery Worker执行文件下载时无报错无日志异常退出求助
问题背景
Celery Worker(基于gevent协程池,运行在Docker容器)在调用requests/urllib启动文件下载后立即退出,无任何错误日志输出,且下载路径文件夹可正常创建,排除权限问题。Worker启动命令如下:
worker1启动命令
celery -A backend worker -P gevent -c 2 -Q default,products --purge --max-tasks-per-child 3000 --without-gossip --without-mingle --loglevel=INFO
worker2启动命令
celery -A backend worker -P gevent -c 2 -Q default,parser --purge --max-tasks-per-child 3000 --without-gossip --without-mingle --loglevel=INFO
服务器配置:4GB内存、Intel Xeon(Cascadelake)2.4GHz×4
排查建议
提升日志级别并完善日志采集
当前INFO级别可能遗漏关键错误细节,将启动命令的--loglevel=INFO改为--loglevel=DEBUG,同时添加--log-signals参数记录信号触发日志。用docker logs -f <worker容器ID>实时跟踪日志,重点关注协程调度、网络IO、进程信号相关输出。检查gevent猴子补丁是否正确执行
gevent需要对标准库进行猴子补丁才能兼容requests/urllib的网络IO,确保在导入requests/urllib之前执行gevent.monkey.patch_all(),且补丁覆盖所有模块(默认参数即可)。未打补丁会导致网络IO阻塞整个协程池,甚至触发进程异常退出。排查内存溢出(OOM)问题
- 给Docker容器设置内存限额(如
docker run --memory=2g --memory-swap=3g ...),避免无限制占用内存被系统OOM Killer强制终止 - 下载大文件时改用流式写入:
requests添加stream=True参数,分块写入磁盘(如iter_content(chunk_size=8192)),避免一次性加载整个文件到内存 - 用
docker stats实时监控Worker容器的内存使用率,确认退出时是否有内存突增现象
- 给Docker容器设置内存限额(如
验证容器退出状态与系统日志
- 用
docker inspect <已退出容器ID>查看退出状态码:状态码137表示进程被SIGKILL终止(大概率是OOM),状态码0可能是任务触发了正常退出逻辑 - 查看宿主机系统日志(
dmesg或/var/log/syslog),搜索Out of memory或killed process关键字,确认是否是系统强制杀掉Worker进程
- 用
测试最小化下载任务
编写极简测试任务排除业务代码干扰:from celery import shared_task import requests @shared_task def test_stream_download(): try: url = "https://example.com/large-file-sample.zip" with requests.get(url, stream=True) as resp: resp.raise_for_status() with open("/downloads/test.zip", "wb") as f: for chunk in resp.iter_content(chunk_size=8192): f.write(chunk) return "download completed" except Exception as e: import traceback print(f"Error detail: {traceback.format_exc()}") raise执行该任务,若Worker仍退出,可排除业务逻辑问题,聚焦基础环境配置。
临时禁用max-tasks-per-child配置
当前设置--max-tasks-per-child 3000,若下载任务刚好是第3000个执行的任务,Worker会自动退出重启。临时去掉该参数测试,或统计任务执行次数,确认是否触发进程轮换机制。
内容的提问来源于stack exchange,提问作者Omkommersind

