日期:2026-08-05
某次大批量导入,调用方把几十兆的文档塞进一个请求体,直接把网关节点的内存打满,连带正常的小请求全部超时。我们当时意识到:网关的第一职责不是接住所有请求,而是挡住会拖垮自己的请求。超大负载防护是稳定性的底线。项目视角很硬:自身不倒,才能服务别人,网关的自我保护优先级高于来者不拒。
场景有四块。一是请求体大小限制:在入口对单请求体设硬上限,超限直接拒绝并返回明确错误。二是流式接收:对合法的大请求改用流式读取,不一次性进内存。三是超限拒绝:拒绝时返回带建议的提示,引导调用方分片,而不是冷冰冰甩个错误码。四是防护水位监控:节点内存、连接数、请求体大小分布实时看板,超水位预警,把事故消灭在苗头阶段。
难点一是限额的设定,太小误伤正常大文档、太大防不住,我们按模型能力和接口类型分级设限。难点二是流式接收的兼容性,部分老客户端不支持分块,我们对这些走特殊通道并打标,避免为了防护牺牲兼容。难点三是水位联动,单纯拒绝不够,我们在内存接近水位时主动降速而非硬拒,给调用方缓冲,把"直接报错"降级成"先慢一点"。
案例片段(已脱敏): 治理后入口对单请求体设了分级上限:常规问答二十兆、文档解析接口一百兆。一次异常客户端并发上传四十三兆单包,网关在解析前就返回四一三错误并提示分片;节点内存峰值从此前的打满降到平稳的约六成,正常请求P99延迟无波动,防护真正做到了"挡得住、不误伤"。
防护上线后,因超大请求导致的节点内存打满事故归零;正常请求P99延迟波动收窄约四成;超限请求拦截率约百分之百;防护水位告警提前量从几乎为零提升到约五分钟。网关稳定性从被动救火转为主动拦截,运维同学夜里睡得踏实了不少。
网关先限负载,保护换稳定,自身不倒才能服务别人。限额要分级,一刀切会误伤或漏防。超限要友好,明确提示比冷冰冰的报错更能减少重复错误。水位要联动降速,硬拒是最后手段而非首选,给调用方缓冲往往比直接拒绝更体面也更稳。
稳定性这种事,靠救火永远救不完。把超大负载挡在门外,看似少接了几单,实际换来的是整条链路的长治久安,这笔账怎么算都值。
我们把超大负载防护推广到所有网关入口时,限额设定是最难的平衡。太小误伤正常大文档,太大又防不住恶意打满。最终我们按接口类型分级设限,问答类小、文档解析类大,并给老客户端留特殊通道保兼容。水位联动我们做了降速加硬拒两档,内存接近水位先降速给调用方缓冲,真到临界才硬拒,把误伤降到最低。防护看板独立成面板,超水位提前约五分钟预警。
第一,网关先限负载,保护换稳定,自身不倒才能服务别人,来者不拒是稳定性大忌。第二,限额要分级,不同接口承载能力不同,一刀切会误伤或漏防。第三,超限要友好,返回明确分片提示比冷冰冰错误码更能减少重复错误。第四,水位要联动降速,硬拒是最后手段而非首选,给调用方缓冲往往更体面也更稳。第五,防护要测不要信,上线前用压测模拟超大包,验证拦截真的生效而不是纸面配置。
第一坑是限额一刀切,早期所有接口统一二十兆,正常的大文档解析被误伤,按接口类型分级后才平息。第二坑是硬拒太生硬,超限直接报错,调用方反复重试反而加剧压力,我们加了明确分片提示才减少无效请求。第三坑是水位无联动,只设硬上限没有提前降速,临界时还是被打满,加了降速档才真正平稳。这几坑让我们确认,防护的本质是给系统留余量、给调用方留缓冲,而不是简单粗暴地关门。
超大负载防护最深的体会是:网关的第一职责是保护自己,自身不倒才能服务别人。来者不拒看似友好,实则是把整个链路的稳定性押在调用方的善良上,一旦有人误发超大包,连无辜的小请求一起陪葬。分级限额加水位联动降速,是把风险关在门外的工程克制。
另一点体会是,防护要测不要信。上线前用压测模拟超大包,验证拦截真的生效而不是纸面配置,我们就在早期吃过配置写了却没生效的亏。把防护也纳入演练,稳定性才闭环。
最后再强调一句,防护的边界要划在入口而不是后端。很多团队把限流逻辑写在模型服务内部,结果是网关已经把请求放进来、内存已经吃紧才被拦,为时已晚。我们把大小限制和水位防护前移到网关入口,本质上是把稳定性的问题在最外层就解决掉,后端只管算、不管挡,职责清晰也更好维护。