Python多进程Worker随机卡顿问题排查求助
问题成因分析
- 共享资源竞争阻塞:如果
process_one_flight中涉及文件读写、数据库操作等共享资源访问,多进程同时操作同一资源时可能引发死锁或阻塞。比如多个进程同时写入同一文件、争抢数据库连接池资源,都会导致进程卡在等待资源释放的状态。 - 队列判断的非线程安全问题:代码中用
while not q.empty()作为循环条件,但q.empty()的结果是瞬时的——在判断队列非空后,其他进程可能已经取走了剩余任务,此时q.get()会进入阻塞状态(默认get()是阻塞式),导致进程无限等待,表现为“卡住”。 - 对象序列化异常:多进程间传递
Flight_lw实例依赖pickle序列化,如果该类包含不可序列化的资源(如打开的文件句柄、未关闭的网络连接),反序列化后的实例状态异常,会导致process_one_flight执行时出现未知阻塞。 - 第三方库/系统调用的进程安全问题:若
process_one_flight调用了非进程安全的第三方库(如某些带有全局状态的计算库),或调用了底层系统API(如文件锁、进程间通信接口),多进程环境下可能触发死锁或未定义行为。 - 系统资源耗尽:多进程同时运行时,若每个进程占用大量内存、文件句柄等资源,会导致系统资源不足,操作系统会挂起部分进程,表现为脚本卡住。
稳定复现方法
- 添加精细化日志:在
process_one_flight的关键步骤(如文件读写前后、第三方库调用前后)插入日志,记录进程ID、当前步骤、时间戳。例如:
这样卡住时能直接定位到具体执行步骤。import logging logging.basicConfig(level=logging.INFO, format="%(process)d - %(asctime)s - %(message)s") # 在关键步骤处 logging.info(f"Processing flight {flight.name}: starting file read") - 固定测试数据集:选取之前出现过卡顿的若干航班数据作为固定测试集,避免每次运行数据不同导致问题无法复现。
- 调整进程数测试:尝试不同的
num_workers值(如2、4、8),观察是否在特定进程数量下更容易触发卡顿,缩小问题范围。 - 替换共享组件:将
Manager创建的队列替换为普通multiprocessing.Queue,或改用concurrent.futures.ProcessPoolExecutor分发任务,排查是否是Manager组件的线程安全问题导致的卡顿。 - 构造资源竞争场景:手动让多个进程同时访问同一航班的文件或资源,模拟真实场景中的竞争情况,触发卡顿。
- 使用调试工具:当脚本卡住时,用
py-spy工具attach到卡住的进程,获取当前调用栈:
通过调用栈可以直接看到进程卡在哪个函数或系统调用上。py-spy dump --pid <卡住的进程ID>
内容的提问来源于stack exchange,提问作者Souhaielrmx
相关产品推荐
相关产品推荐

