AI网关调用超时传播与上游取消(cancel propagation)落地

日期:2026-08-17

一、项目背景

我们的 AI 网关后面挂着好几个大模型实例,有些请求后端要算二三十秒。问题出在链路前端。前端页面有自己的超时,比如八秒没响应就断开重连,可网关不知道前端断了,还傻等后端把活干完,连接和显存一直占着。量一上来,网关侧堆了一堆没人要的结果,后端算力被这些废活吃满,正常请求反而排不上,整条链路像被自己人堵死。那次我们查了半天才定位,超时没往下游传。

二、落地场景

现在请求一进来就带一个上下文超时,前端断没断网关都清楚。前端真断开了,网关立刻收到信号,把这个取消信号顺着往下传给后端模型服务。后端不是装作没看见,而是真的中断正在算的任务,把占着的显存和连接腾出来。超时和重试也拆开了,网关自己有重试策略,但上游已经取消的请求不再重试,避免重复占资源。整条链路从前端到后端,超时是一根贯穿的线。

三、关键技术挑战与解决思路

首先要解决的是超时上下文怎么透传。我们用了支持取消传播的调用框架,请求上下文里带截止时间,每一跳都读同一个截止时间,不被中间环节重置。接着要解决的是取消信号可靠送达,网络抖动可能丢信号,我们在后端加了兜底,按上下文截止时间自己判断过期就停,不单纯依赖上游来通知。还有一块难啃的是重试和取消的冲突,取消的诉求是别再浪费资源,重试的诉求是提升成功率,我们定了个规则,上游显式取消的绝不重试,只有网关侧自身瞬时错误才重试。

案例片段(已脱敏): 超时传播与取消信号配置片段(字段示意):request_ctx:  deadline_propagation: true  on_upstream_cancel: propagate_to_backend  backend_cancel: hard        # 后端真正中断推理任务  retry:    on_explicit_cancel: false    on_transient_error: true一次压测:模拟前端 8s 超时断开,旧逻辑后端仍跑满 25s,连接占用 320 个;新逻辑收到取消后 0.4s 内中断,连接占用降到 40 个,后端算力释放明显。

四、效果数据

无效占用的连接数在超时场景下下降约九成,因为上游一断后端就停。平均资源释放时长从等后端跑完的二三十秒收到一秒内,显存周转快了很多。级联超时事故基本消失,之前那种前端断了后端还在算、越积越多的死循环没再出现。后端算力浪费下降明显,正常请求的排队时间短了。得坦白,兜底截止时间我们一开始没配,靠信号送达,结果少量丢信号的请求还是跑满全程,加了本地截止才彻底解决。

五、可复用经验总结

超时传播这事,本质是让整条链路说同一种时间语言,前端说不要了,后端别假装没听见。取消信号要真中断任务,光在网关层丢弃结果是没用的,算力还在后端烧。重试和取消必须分清,这层我想明白之前吃过亏,曾经对取消的请求也重试,结果是加倍浪费。本地截止兜底这个细节,是我被丢信号坑了之后加的,任何依赖网络送达的机制都得有自己的保命线。这套后来我们和优雅关闭那套一起用,升级和超时都安静了。

结语

超时传播本质是让整条链路说同一种时间语言,前端说不要了,后端别假装没听见。我们那次查了半天才定位,超时没往下游传,后端还在傻算,连接和显存被废活吃满,正常请求排不上。取消信号要真中断任务,光在网关层丢弃结果没用,算力还在后端烧。重试和取消必须分清,这层我想明白前吃过亏,曾对取消的请求也重试,结果是加倍浪费。本地截止兜底是我被丢信号坑了之后加的,任何依赖网络送达的机制都得有自己的保命线。现在这套和优雅关闭一起用,升级和超时都安静了,上游终于不再被我们拖挂。压测时我们专门模拟了前端中途断开,旧逻辑连接占用三百多个,新逻辑零点几秒就释放,差距一眼可见。后端我们加了按截止时间自己停的兜底,不单纯等上游通知,丢信号的请求也不会跑满全程。取消信号走上下文透传,每一跳读同一个截止时间不被重置,当初定死才没乱。链路级时间一致性是推理服务扛压的前提,这次踩通之后别的服务也照做,故障率明显下去了。后端按截止时间自停我们一开始担心误杀正常长请求,后来发现正常请求都有合理截止,误杀几乎为零。压测那次对比我们录了屏,给老板看连接数从三百多掉到四十,预算一下子批了。取消传播现在也是我们接口规范的硬要求。

我们把取消传播写进了接口规范,新接的模型服务默认带 deadline 透传,不带的构建就卡住。后端按截止时间自停,我们一开始担心误杀正常长请求,跑下来发现正常请求都有合理截止,误杀几乎为零。压测那次对比录了屏,连接数从三百多掉到四十,老板看完预算直接批了。链路级时间一致性现在成了推理服务扛压的前提,别的团队也照着做。