快速结论:该问题通常发生在 LiteLLM Proxy 流式转发(stream=true)过程中,客户端中途断开或停止读取时,Proxy 未关闭上游 LLM 连接,导致后端持续生成或阻塞;应优先排查客户端断开路径上是否真正调用了 CustomStreamWrapper.aclose(),以及超时配置是否兜底。
适用环境:Issue 复现环境为 litellm_internal_staging @ 0d120de785、uvicorn 0.33.0(ASGI spec_version 2.3)、starlette 1.1.0;评论中的实测环境为 LiteLLM 1.105.1、vLLM 0.31.0、Qwen3-8B、单张 L4。Proxy 使用 openai/mock-model 指向本地 OpenAI 兼容 mock 后端。
最快修复方案:暂无确认的一步修复方案。Issue 明确指出 CustomStreamWrapper.aclose() 逻辑本身正确,问题在于断开路径上没有任何地方调用它;评论中的实测表明配置 1 s LiteLLM 超时可在三种客户端行为下停止上游,但这只是该场景下的规避手段,不是 Issue 验证过的代码修复。
注意事项:评论中的超时实测使用的是 openai/ provider 前缀,并未覆盖 hosted_vllm/ 路径(该路径由 #30245 修复)。短超时会影响正常长流式响应的可用性,是否适用于生产需自行评估。
问题场景
用户在 LiteLLM Proxy 上发起流式聊天补全请求(stream: true),后端为自托管的 vLLM / TGI / SGLang 等 OpenAI 兼容服务。客户端在流式传输中途断开连接,例如 curl 被 --max-time 杀掉,或 OpenWebUI 等 UI 点击停止并关闭连接。此时 Proxy 停止读取上游流,但不会关闭它。
报错原文
[Bug]: Proxy keeps upstream LLM connection open after a streaming client disconnects; backend keeps generating or stays blocked
原因分析
Issue 给出的根因是:CustomStreamWrapper.aclose() 存在且能正确关闭上游流,但断开路径上没有任何调用方。在 uvicorn 0.33(ASGI spec_version 2.3)下,Starlette 的 StreamingResponse 会让 stream_response 与 listen_for_disconnect 竞争;一旦检测到断开,它会直接放弃 body 迭代器,而不调用其 aclose()。
由此,生成器链(combined_generator → async_streaming_data_generator / async_data_generator → CustomStreamWrapper)被挂起,只在 GC 时才可能被终结。上游连接因此保持 ESTABLISHED:小响应被写入 TCP 缓冲区,后端误以为正常完成;大响应(如 256KB 分块)会填满缓冲区并让后端永久阻塞。对 vLLM 而言,对应的 GPU 生成槽位会一直占用。
可能的相关影响:断开前已流出的 token 不会计入 spend log,因为 CustomStreamWrapper 只在自然收到最后一个 chunk 时触发日志。
环境排查
- 确认 uvicorn 版本是否为 0.33.x,以及 ASGI
spec_version是否为 2.3(该行为在 Issue 中与 starlette 1.1.0 组合复现)。 - 确认 Starlette 版本。
- 确认 LiteLLM 版本(复现版本为 litellm_internal_staging @ 0d120de785;评论实测为 1.105.1)。
- 确认后端类型与版本,Issue 涉及 vLLM(评论实测 0.31.0)、TGI、SGLang。
- 确认 Proxy 配置中 provider 前缀是
openai/还是hosted_vllm/,两者修复路径不同。 - 确认是否配置了 LiteLLM 超时;评论实测 1 s 超时可使上游停止。
解决步骤
- 先在测试环境复现并观察上游连接状态:客户端中途中止流式请求后,用
lsof -nP -iTCP:9090 -sTCP:ESTABLISHED检查 Proxy 与后端之间是否仍有 ESTABLISHED 连接,并查看后端日志是否出现 abort/完成记录。 - 对照环境确认 uvicorn / starlette 版本是否命中上述断开时跳过
aclose()的路径,缩小问题范围。 - 可优先尝试:在 LiteLLM 侧配置较短的请求超时(评论中 1 s 超时在“客户端关闭连接”“停止读取但保持 socket”“读到结尾”三种行为下都停止了上游)。注意这只是规避,且会限制正常长流式请求。
- 若使用
hosted_vllm/provider,请关注 #30245 中的修复,而不是按评论中的openai/配置结论处理。 - Token 计费方面,由于断开前已流出的 token 不会写入 spend log(参见 #14457),如有计费需求需单独核对,不要依赖日志完整性。
验证方法
重复断开场景:客户端中止后,检查 Proxy 到后端的连接是否在短时间内消失,后端日志是否记录到 abort 而非继续生成或长时间挂起;若后端为 vLLM,可观察对应请求的生成槽位是否及时释放。评论中的方法是通过 vLLM 0.31.0 scheduler 统计取消后接受的 token 数,与直连 vLLM 对照,以此确认上游是否真正被停止。
参考来源
AI 工具推荐
想把多个 AI 模型放在一个入口?
GamsGo AI 集成 ChatGPT、DeepSeek、Gemini、Claude、Midjourney、Veo 等常用模型,适合写作、绘图、视频和日常 AI 工作流。
推广链接:通过此链接购买,我可能获得佣金,不影响你的价格。
这个方案解决了吗?
可以继续搜索完整报错,或查看同一工具的其他排查指南。
![[Bug]: user_config routing discards the Router before the call runs](https://www.chat-gpts.plus/wp-content/uploads/2026/10/43486-47692012-768x403.jpg)
![[Bug]: Responses API forwards client_metadata to custom_openai chat completions](https://www.chat-gpts.plus/wp-content/uploads/2026/10/29834-c9b4a778-768x403.jpg)
