记录一下那天晚上的排查过程。生产者把两千条任务放进 asyncio 队列后 await queue.join(),进程 CPU 降到 0%,日志停在等待 join,所有任务其实已经处理完了。

刚开始盯着「put 之后没 await 导致计数不准」,折腾了半个多小时,排掉了。

把日志和配置对完,能解释这个现象的基本就这几处。消费协程处理完没调 task_done。少数情况下是异常分支提前 return 跳过了 task_done。

另外,任务被 cancel 后未完成计数永远不为零。

第一件事是确认每个 get 是否配对 task_done

grep -c "task_done" worker.py

接着用 try finally 包住消费循环

python -c "print('try: await handle() finally: q.task_done()')"

然后加超时打印未完成计数定位

python q_debug.py --timeout 5 --show-unfinished

剩下的就是重跑并观察 join 是否返回

python run_queue.py --tasks 2000

命令输出我都留了记录,免得改完记不清原来的值。

怎么算真的好了,看的是同一批现象。join 在全部任务完成后立即返回,未完成计数归零,进程正常退出。

这里还有个坑。队列的未完成计数是配对账本,少一次 task_done 就永远等不到。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189