fix: 流式请求客户端断连后继续读取上游响应,避免 usage 丢失 - #4464
Conversation
StreamScannerHandler 中 scanner goroutine 和主循环监听了 c.Request.Context().Done(), 客户端断连时立即停止读取上游响应流,导致最后的 message_delta(含 output_tokens) 丢失,计费记录不完整,造成上下游账单差异。 修复:去掉 scanner goroutine 和主循环中的 c.Request.Context().Done() 监听。 客户端断连后 scanner 继续读完上游流拿到完整 usage 数据再退出。 Fixes QuantumNous#4463
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe handler removes checks for client disconnection ( Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
这不应该算是bug,不能算作修复,大部分提供商支持流模式中断,如果需要忽略客户端断开可以用nginx等网关配置 |
看你决策吧,因为有些供应商就算支持了,但是可能因为回传的各种网络波动什么的,导致超时失败,这个是我发现计费异常定位发现的,如果什么依赖第三方,例如供应商,例如网关配置,那我觉得这个有点太多约束了 这个问题让我昨天发现丢了10个请求的钱,我搞了个财务统计系统才发现,否则在大流量下有盈利就被覆盖看不出来了 |
但是这个问题会导致有人在请求是恶意取消,实现请求免单,是否最起码应该只要开始响应了,最起码计费个预估输入? |
|
目前就是按照已输出文本估算计费的,计费为0可以看看自己是不是关了流模式本地计费 |
Nginx的location 无论设置了 proxy_ignore_client_abort on; 还是如何设置,都没有效果,都无法实现 Nginx 层面实现 客户端中断,newapi继续请求。是否可以加个设置? |
成功了,在 nginx 的 location 配置加以下参数就行 如果希望只改 /v1/responses 的 endpoint 不影响其他 endpoint 话,可以把 location 复制一份,然后 location ^~ / 匹配改为 location = /v1/responses ,后面增加以上配置就行,完整 location 示例如下 |

问题
StreamScannerHandler(relay/helper/stream_scanner.go)中,scanner goroutine 和主循环都监听了c.Request.Context().Done()。客户端断连时 scanner 立即停止读取上游响应流,导致最后的message_delta事件(含output_tokens等 usage 信息)丢失,计费记录不完整,造成上下游账单差异。根因
case <-c.Request.Context().Done()→ 客户端断连立即 returncase <-c.Request.Context().Done()→ 客户端断连结束整个流程修复
去掉 scanner goroutine 和主循环中的
c.Request.Context().Done()监听。客户端断连后 scanner 继续读完上游流拿到完整 usage 数据再退出。不影响资源回收:
[DONE])ticker)兜底防止无限阻塞stopChan机制确保所有 goroutine 正确退出c.Request.Context().Done()检查(客户端断连后无需继续 ping,且 ping goroutine 正常退出不会触发stopChan)实际案例
通过对比上下游账单发现:上游 100 条记录中有 2 条在 new-api 侧缺失计费记录(
quota=0),均为客户端断连导致 scanner 提前停止、未读到 usage 事件。Fixes #4463
Summary by CodeRabbit