AI 网关调用方请求合并与批量接口降本落地

日期:2026-08-21

一、项目背景

我们网关后面有个业务方,一次页面渲染要打十几个小模型调用,每个都走一遍鉴权、路由、计量、日志,网关侧的处理开销有时候比后端模型推理还贵。QPS 一高,连接数先爆的不是模型服务,是我们的网关,业务方还反过来怪我们网关慢。我们拉监控一看,单请求平均 payload 才几百字节,但每个请求都要建连、鉴权、写计量,这种"小调用高频过网关"的模式,把网关活活拖成了瓶颈。问题的本质是:网关按"每次调用"计费和管理,但业务方按"一次用户动作"看待这些调用,两边粒度对不上。

二、落地场景

我们落地的办法是把"碎调用"在网关侧聚合成"批量动作"。第一块是批量接口封装,业务方把原来十几个小调用打包成一个 batch 请求,网关内部扇出到各个模型,再把结果归并成一个响应返回。第二块是请求合并网关,对同源同目的地的极碎调用,网关在入口侧做时间窗合并,攒一小批再统一往下发。第三块是单次计量与配额,批量接口按"一个 batch"记一次调用、算一次配额,而不是按内部扇出的十几条算,计量口径和业务方认知对齐。第四块是合并上限保护,限制单个 batch 的条数和超时,防止有人塞巨量请求把后端打挂。

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

合并边界判定是最棘手的部分。哪些调用能合并、哪些不能,得看它们是否独立、是否同源、是否同优先级。我们第一版做得太激进,把不同优先级的调用也合并了,结果一个低优先的批量拖慢了里面高优先的请求,核心链路被殃及。后来合并只在同一优先级、同源、且超时预算可共享的请求间进行,跨优先级的绝不合并。扇出一致性也是个坑:批量里某条子调用失败,整体该怎么返回?我们最初设计成"一条失败全失败",业务方说这样太脆,一条无关紧要的子调用挂了整页渲染失败。改成"部分失败返回成功子集加失败标记",业务方自己决定怎么降级,韧性好很多。

合并上限我们起初只设了条数上限,没设超时上限,有人一次塞了五百条进来,网关扇出后后端某模型被打满,连带影响了其他调用方。之后改成"条数加单条超时加总超时"三重保护,滥用被压住。

四、效果数据

批量接口上线后,该业务方对网关的调用次数下降约九成,连接数同步下降约八成五,网关侧开销占整体推理成本的比重从约三成降到约百分之五。平均响应耗时按用户动作算,反而因为少了建连和鉴权开销,从约一点六秒降到约一点一秒。合并命中率(能合并的请求占比)在忙时约七成。合并上限保护上线后,因超大批量导致的后端过载事件归零,其他调用方受牵连的工单同比下降约九成。

案例片段(已脱敏): 批量接口配置:batch.max_items = 50,per_item_timeout_ms = 800,total_timeout_ms = 3000,merge_window_ms = 15,仅同优先级同源合并。某页面渲染原 16 个单调用合并为 1 个 batch,网关内部扇出至 4 个模型,成功 15 条、1 条超时返回失败标记。计量记 1 次 batch 调用,配额扣减对应 1 次。监控:该 batch 网关处理耗时 220ms(原 16 次独立调用累计网关开销约 1.4s),后端推理耗时 780ms,总响应 1.05s。

客户端改造成本这事我们预判不足。批量接口要业务方把十几个单调用改成调一个 batch,看似简单,但他们前端代码里这十几个调用分散在不同组件里,聚合要重构调用层,排期排了快两周。为了降低阻力,我们顺手写了个轻量 SDK,把"发起单调用"的接口保留,底层自动在网关侧合并,业务方几乎零改动就能享受合并收益,采纳率一下从勉强过半变成几乎全量。这个经验后来反复验证:网关侧的优化如果要求业务方大改,落地必打折,能在网关透明做掉的就别推给调用方。合并后的计量展示我们也改了,调用方在账单里看到的是"batch 调用一次",和他认知的"一次用户动作"对齐,对账争议直接消失,技术收益之外还顺手解决了商务扯皮。

五、可复用经验总结

小调用高频过网关这种用法,本质是粒度错配,业务方按动作看、网关按请求管,不把粒度对齐,网关永远是被冤枉的那个慢。批量接口加请求合并是治本的手段,但合并边界要守纪律,跨优先级的合并看似省事实则埋雷,我们吃过核心链路被低优先拖慢的亏之后就把这条写进硬规则。部分失败的处理别一刀切,返回成功子集比全失败韧性高得多,业务方要的是能降级不是全崩。合并上限这事我现在的看法是越多重保护越好,条数、单条超时、总超时缺一不可,因为滥用者总会找到你没堵的那个口子。这套批量思路后来在另一个多模型编排场景也用了,把"一次用户问题"对应的多步推理合并计费和限流,效果同样明显。