我正在通过 redis 后端在 docker 中运行芹菜。我有
- 芹菜打容器
- 芹菜工人容器
- 瑞迪斯容器
芹菜工作器容器生成 6 个工作进程。如果芹菜任务遇到异常,则辅助角色(所有辅助角色)将停止消耗作业。我尝试稍微调试一下进程,似乎单个进程将卡在读取pipe
而其余进程将卡在futex
调用上。
调试信息:
# Worker 1
$ sudo strace -p 15959 -s 10000
strace: Process 15959 attached
read(4, ^Cstrace: Process 15959 detached
<detached ...>
# Worker 2 through N
$ sudo strace -p 15960 -s 10000
strace: Process 15960 attached
futex(0x7f95c3f94000, FUTEX_WAIT_BITSET|FUTEX_CLOCK_REALTIME, 0, NULL, 0xffffffff^Cstrace: Process 15960 detached
<detached ...>
$ sudo lsof -p 15958
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
celery 15958 root txt REG 0,197 32248 264184 /usr/local/bin/python3.5
...
celery 15958 root 4r FIFO 0,12 0t0 348559 pipe # frozen here
奇怪的是,工人将永久处于冻结状态,除非发生以下 2 件事之一:
- 重新启动工作线程 (
docker restart celery-worker
) - 快速启动芹菜。
我觉得"快速启动芹菜"很有趣。通过发出此命令,所有工作人员都会"醒来"并恢复活力并开始消耗任务,直到下一个异常。
docker exec -it celery-worker celery -A CELERY_APP inspect active
在这里,工人又复活了。
$ sudo strace -p 15958 -s 10000
strace: Process 15958 attached
read(4, " 336", 4) = 4
read(4, "2003K2(MjnNccelery.app.tracen_fast_trace_tasknq (X" tasks.status_taskq1X$ 0071bf9972-cf5b-4a20-a8b7-ce4d7921fe0dq2}q3(Xt parent_idq4NX4 langq5X2 pyq6X3 etaq7NX5 groupq10NX7 expiresqtNXt timelimitqn]qv(NNeX6 originqfX21 gen1@03e7668436e5qrX10 argsreprq16X2 ()q17Xn kwargsreprq20X2 {}q21X10 reply_toq22X$ 005ad0db0b-a759-375c-b173-07598914633eq23X4 taskq24h1X16 correlation_idq25X$ 0071bf9972-cf5b-4a20-a8b7-ce4d7921fe0dq26X7 root_idq27X$ 0071bf9972-cf5b-4a20-a8b7-ce4d7921fe0dq30X7 retriesq31K Xr delivery_infoq32}q33(X10 priorityq34K X10 exchangeq35X q36Xv redeliveredq37NXv routing_keyq X6 celeryq!uX6 shadowq"NX2 idq#h2uCM[[], {}, {"chord": null, "chain": null, "errbacks": null, "callbacks": null}]q$X20 application/jsonq%X5 utf-8q&tq'}q(tq)206q*.", 798) = 798
futex(0x7f95c3f94000, FUTEX_WAKE, 1) = 1
write(7, " 342003K (MjnNG@327204T2132121\KnNtq 206q1.", 32) = 32
getpid() = 10
知道这是为什么吗?这是一个错误吗?我可以配置一些东西,以便芹菜不会在任务异常时挂起?
我正在使用eventlet
并且我正在使用默认的pre-fork
池运行工作线程。切换到eventlet
池似乎已经解决了问题。
即
celery worker -A CELERY_APP --pool eventlet