日期:2026-11-08
我们的 AI 网关接了一批大报文场景,有些接入方把整篇文档甚至批量数据直接塞进单次请求体,单个请求几 MB 是常事。网关的内存和后端解析一开始是按 KB 级设计的,遇到这种大报文,要么把网关内存峰值顶上去,要么后端解析超时,偶尔还有人误传超大文件,把整条链路拖到几乎不可用。我们当时收到过一次告警,一个十几 MB 的请求把单节点网关的内存打满,邻居的推理调用跟着超时。
这个项目要做的,不是让网关去硬扛所有大报文,而是分级治理:合理的大的要能走通,不合理的超大和误传要被拦在门外,同时把内存和解析控制在安全线内。
落地后,网关在入口按请求体大小做分级。常规 KB 级请求直接放行走正常流水线;较大但合理的请求走流式解析和分块处理,不一次性读进内存;超过阈值的超大请求直接拒拦,返回明确错误码和提示,不让它进后端。
我们对不同业务域设了差异化的阈值,文档类接口允许大一些,普通对话接口卡得紧,避免一刀切把正常业务误伤。超限请求会进审计和告警,运维能看见是谁在传什么,而不是默默失败。后台看超大报文拦截数、网关内存峰值、解析失败率和正常大请求误拦率。
我们当时还补了一层,对接入方的调用方做额度关联,频繁试探大阈值的调用方会被标记,防止有人拿大报文做压力攻击。这块和网关的限流熔断是联动的,大报文防护不是孤立的一层。
绕不开的是大小阈值的分级。阈值定太低,正常文档场景被误拦;定太高,防护形同虚设。我们按业务域拆了三档阈值,文档域最宽,对话域最紧,运营可在后台调,不写死在代码里。这个可调能力后来被证明很关键,业务迭代时不用改发版。
紧接着要处理的是流式解析的内存控制。大请求不能一次性读进内存,我们改成边读边解析、分块转发后端,网关侧内存占用和报文大小脱钩,只和并发数相关。这样几 MB 的请求也不会把节点内存打爆。
再往下是超限拒绝与友好提示。直接断连接体验差,我们返回结构化的错误码和"请求体超过 X MB,请改用分块或批量接口"的提示,让接入方知道怎么改,而不是只看到连接被拒。这比单纯拒拦减少了大量工单。
最后是误拦正常大请求。分级阈值和流式处理后,正常大请求能走通,我们持续盯误拦率,一旦某业务域误拦率升高就调阈值。防护的目标是拦住异常,不是拦住业务,这个边界要守。
案例片段(已脱敏): 请求体分级与流式解析配置(节选):
body_size: tiers: chat_domain_max_mb: 1 doc_domain_max_mb: 16 default_max_mb: 4 stream_parse: true # 大请求流式分块,内存与大小脱钩 reject_code: 413 reject_hint: "请求体超限,请改分块/批量接口" audit_on_reject: true caller_quota_link: true # 与限流熔断联动防护上线日志:单节点内存峰值由 5.2GB 降至 1.8GB,超大报文拦截日均 230 次,误拦率 0.2%。
防护上线后,单节点网关内存峰值从五点二 GB 降到一点八 GB,超大报文不再能打满内存拖垮邻居。日均拦截超大报文约两百三十次,其中绝大多数是误传和异常重试,正常业务请求几乎不受影响,误拦率维持在千分之二以下。
解析失败率,主要是大请求流式解析的中断,控制在万分级,且都伴明确错误返回,没有再出现静默卡死。接入方接到结构化拒绝提示后,改用分块接口的比例明显上升,从源头减少了大报文。文中数据为项目复盘口径,均为示意值,非审计级精确数字。
我们当时担心分级阈值会让运维变复杂,实际把阈值收进后台配置后,业务域自己调,网关团队反而更轻松。倒是审计告警的量比预期大,后来加了聚合才不至于刷屏。
网关对大报文不能硬扛,分级拒拦比无脑接收稳得多,合理的大的走流式解析,不合理的超大挡在门外。阈值别一刀切,按业务域拆档并收进后台可配,业务迭代时不用改发版,这点很值。
大请求务必流式分块处理,让内存占用和报文大小脱钩,只跟并发相关,否则几 MB 就能打爆节点。超限拒绝要给结构化提示和改法,别只断连接,否则工单会淹死你。防护的边界是拦异常不是拦业务,误拦率要持续盯。
这个项目里我后来觉得,分级阈值收进后台配置是个正确决定,本来担心运维变复杂,结果业务域自己调,网关团队反而更轻松。倒是审计告警量比预期大,吃了亏才加了聚合,这种小坑不踩不知道。防护的边界始终是拦异常不是拦业务,误拦率要一直盯,我们曾因阈值偏紧误拦过正常文档请求,被接入方投诉后才调到合适的档。
顺带,审计告警一定要加聚合,不然大报文一多能把运维群刷爆,我们吃过这个亏。分级阈值也别一设就不动,业务域迭代时要回头看误拦率,阈值是活的不是死的。