Celery+Redis下find_faces任务批量运行偶发卡住无报错问题求助
解决方案
核心问题定位
你遇到的任务永久卡在started状态无报错的核心原因是face_recognition底层依赖dlib的C扩展实现,执行期间Python信号机制无法生效,你配置的软时间限制无法触发,导致异常卡死后没有重试逻辑被执行,再叠加Celery默认预取配置、低版本chord的已知问题,最终大批量任务时出现异常。
需要调整的Celery配置&参数
1. 补充硬时间限制配置
软时间限制CELERYD_TASK_SOFT_TIME_LIMIT依赖Python信号触发,仅能中断Python层面执行的代码,无法中断C扩展运行的逻辑,必须额外配置硬时间限制,超时后Celery会直接销毁运行任务的worker进程,触发重试逻辑:
- 全局配置新增:
CELERYD_TASK_TIME_LIMIT = 90(比最长任务耗时高3倍即可,你单张最长30秒设90足够) - 也可以直接给任务单独加参数,优先级更高:
@app.task(bind=True, max_retries=5, soft_time_limit=60, time_limit=90) def find_faces_task(self, document_id, use_cuda=settings.USE_CUDA): # 原有任务逻辑
2. 调整worker预取配置
Celery默认worker会预取多个任务到本地缓存,CPU密集型任务大批量执行时容易导致任务在worker本地排队超时,将预取数设为1,让worker每次仅领取1个任务,避免囤积:
- 全局配置新增:
CELERYD_PREFETCH_MULTIPLIER = 1 - 启动worker时也可以通过参数指定:
celery -A your_project worker --prefetch-multiplier=1
3. 优化worker并发数
人脸检测是典型CPU/CUDA密集型任务,worker并发数不要超过CPU核心数,过多并发会导致CPU资源争抢,任务处理时间异常变长:
- 比如8核CPU启动worker时指定并发数:
celery -A your_project worker --concurrency=6(预留2个核心给系统进程)
4. 修复Redis broker相关配置
你使用Redis作为broker,需要调整可见性超时、连接池参数,避免大批量任务时连接不足、任务被误判为失效:
- 全局配置新增:
CELERY_BROKER_TRANSPORT_OPTIONS = { 'visibility_timeout': 3600, # 任务最长执行超时时间,设为比硬时间限制高即可 'max_connections': 100, 'socket_timeout': 30, 'socket_connect_timeout': 30 }
5. 修复chord相关配置
Celery 4.0.x版本的chord存在大量已知bug,大批量任务时容易出现回调异常:
- 确保已配置正确的结果后端:
CELERY_RESULT_BACKEND = 'redis://your_redis_host:port/db' - 调大chord解锁重试次数:
CELERY_CHORD_UNLOCK_MAX_RETRIES = 60
可选优化项
- 将任务内部的所有
import语句移到文件顶部,避免每次任务执行重复导入的开销 - 开启worker的
--autoscale参数,高峰期自动扩容,低峰期自动缩容:celery -A your_project worker --autoscale=10,3(最大10个worker,最小3个)
内容的提问来源于stack exchange,提问作者user1045680
相关产品推荐
相关产品推荐

