你做了一个AI聊天应用,用户问了一个问题,服务器调用大模型API开始流式返回答案。一切看起来都很正常。然后用户关掉了浏览器标签页。

响应消失了。但那个大模型请求呢?如果你的服务器没有显式传播取消信号,答案可能是:它还在继续跑。

打开网易新闻 查看精彩图片

这不仅是正确性问题。对AI应用来说,这是成本问题。用户可能在生成500个token后就放弃了,而你的后端还在为剩余几千个token继续付费。

两条HTTP连接的生命周期

这里其实有两条HTTP连接。第一条是浏览器到服务器的连接,由浏览器控制。第二条是服务器到大模型API的连接,由你的服务器控制。当浏览器关闭标签页时,第一条连接断开了,但第二条连接不会自动收到任何取消通知。

服务器和大模型请求是两个独立操作,需要显式地把它们的生命周期连接起来。否则,用户关掉页面,上游请求依然在跑,账单也在继续累积。

最简单的服务器写法

一个最简单的实现可能是这样:服务器收到请求后,用fetch调用大模型API,把响应体直接流式返回给浏览器。这段代码能正常工作,但它没有处理取消路径。

当浏览器断开连接时,服务器端的fetch调用不会自动取消。大模型还在生成token,服务器还在接收数据,只是没人消费了。

解决方案:用AbortSignal打通取消链路

正确的做法是在服务器端监听客户端断开事件,然后通过AbortSignal把取消信号传递给fetch调用。这样,用户关掉标签页时,服务器会主动取消对大模型API的请求,停止计费。

具体来说,需要在Hono或Node.js的请求处理函数中,获取请求的取消信号,然后把它传给fetch的options。当浏览器断开连接时,这个信号会被触发,fetch调用随之终止。

这个改动看似简单,但对AI应用的成本控制至关重要。在高并发场景下,被浪费的token费用会快速累积。用户关掉页面不是罕见操作,而是常态。如果你的应用没有处理这条取消路径,每一分钟都在为没人看的生成内容付费。