vLLM推理服务假死排查-多模态缓存幽灵Key导致死循环
type
Post
status
Published
date
Jul 1, 2026
slug
260701-vllm
summary
生产环境中的vLLM推理服务突然假死:进程存活、显存正常占用、健康检查端点返回正常,但所有推理请求全部超时。GPU-util为0,CPU拉到100,极端环境出现,特指高并发
tags
开发
category
技术分享
icon
password
契机环境说明故障现象诊断过程外部观测debug日志分析Metrics端点py-spy抓栈strace确认源码分析验证复盘修复方案touch-不存在的key不操作popitem—跳过并清理幽灵key复现路径总结写到最后
契机
生产环境中的vLLM推理服务突然假死:进程存活、显存正常占用、健康检查端点返回正常,但所有推理请求全部超时。GPU-util为0,CPU拉到100,极端环境出现,特指高并发
环境说明
- 推理框架:vLLM-v0.23.0
- 模型:多模态大模型
- 驱动:Driver Version: 575.57.08
- cuda:release 12.9, V12.9.86
- 启动参数:
- 运行时长:服务已稳定运行数天(约 100 万次迭代),突发假死
这里多说一嘴,由于我是12.9的驱动所以装vllm相当吃力,生产环境又不敢升级驱动,如果你刚好也是12.x驱动,一定要求https://vllm.ai/找安装方法,并且安装过程需要把加速源全部禁用,安装过程中观察下载连接和地址,一定不要从镜像下载! pip install vllm --extra-index-url https://wheels.vllm.ai/0.24.0/cu129 --extra-index-url https://download.pytorch.org/whl/cu129 --index-strategy unsafe-best-match
故障现象
检测项 | 状态 | 备注 |
进程 PID | 存活 | EngineCore |
GPU 显存 | 正常 | 正常 |
GPU 利用率 | 0% | 异常 |
CPU 利用率 | 136% | EngineCore 进程,异常高 |
/health 端点 | 200 OK | 正常返回 |
/v1/models 端点 | 200 OK | 模型列表正常 |
/v1/chat/completions | 超时 | 15s+ 无响应 |
诊断过程
外部观测
debug日志分析
Metrics端点
py-spy抓栈
strace确认
源码分析
刚好去搜索日志中的异常
结论:
- touch() 方法(cache.py#L120-L124)对不存在的 key 将其写入内部 LRU 顺序链表 __order,但不写入实际缓存数据 _Cache__data
- get_and_update_item()(cache.py#L660)在 assert 失败时,__setitem__ 未被执行,但 touch() 已写入的幽灵 key 残留在 __order 中
- 后续任意请求触发缓存写入 → __setitem__ 进入驱逐循环
- popitem() 从 __order 取出幽灵 key → pop() 找不到实际数据 → currsize 不减 → 死循环
验证复盘
完全匹配的已知 Bug,与我们的 py-spy 堆栈、日志、时间线一致
位置 | 代码 | 问题 |
cache.py#L120-L124 | touch() 的 except 分支 | 将不存在的 key 写入 __order,产生幽灵 key |
cache.py#L196-L208 | popitem() 驱逐逻辑 | 未检查 key 是否真实存在于缓存中 |
cache.py#L658-L664 | get_and_update_item() | touch() 和 __setitem__ 之间非原子,异常导致不一致 |
修复方案
本着不升级vllm的方案,我直接去改conda环境中包的源码
touch-不存在的key不操作
popitem—跳过并清理幽灵key
两层防御:改动1从源头杜绝幽灵key产生,改动2确保即使有其他路径产生幽灵key,驱逐时也不会死循环
对应上游PR:vllm-project/vllm#43595,已合入v24
复现路径
- vLLM v0.23.0 或更早版本
- 使用多模态模型(视觉-语言模型),启用prefix caching
- 在缓存接近容量上限时,发送一条触发了多模态hash不存在于缓存的请求
单元测试如下
总结
- 这个bug只存在于vllm23版本,如果遇到和我一样的问题,你能升级就直接升级
- vLLM的health 端点只检查APIServer进程存活,不验证EngineCore是否正常工作。生产环境应增加推理探活端点
- py-spy通过/proc读取内存采样调用栈,不需要ptrace权限,不需要重启进程,不修改任何内存。是排查python进程假死的首选工具
- CPython的GIL使得一个线程的死循环可以冻结整个进程。所有需要与EngineCore交互的操作(调度、模型执行、日志输出)全部被阻塞
写到最后
Prev
将进酒
Next
Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
Loading...

