vLLM推理服务假死排查-多模态缓存幽灵Key导致死循环

type
Post
status
Published
date
Jul 1, 2026
slug
260701-vllm
summary
生产环境中的vLLM推理服务突然假死:进程存活、显存正常占用、健康检查端点返回正常,但所有推理请求全部超时。GPU-util为0,CPU拉到100,极端环境出现,特指高并发
tags
开发
category
技术分享
icon
password
 

契机

生产环境中的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确认

    源码分析

    刚好去搜索日志中的异常
    结论:
    1. touch() 方法(cache.py#L120-L124)对不存在的 key 将其写入内部 LRU 顺序链表 __order,但不写入实际缓存数据 _Cache__data
    1. get_and_update_item()(cache.py#L660)在 assert 失败时,__setitem__ 未被执行,但 touch() 已写入的幽灵 key 残留在 __order 中
    1. 后续任意请求触发缓存写入 → __setitem__ 进入驱逐循环
    1. 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交互的操作(调度、模型执行、日志输出)全部被阻塞
     

    写到最后

    notion image
    是在往前走就好 bothsavage.github.io
     
    notion image
     
    Prev
    将进酒
    Next
    Trae远程开发中DeepSeek自定义模型4054错误的排查与修复
    Loading...
    Article List
    talk is cheap
    技术分享
    万里长征
    心情随笔
    知行合一