AI 网关异常检测与自适应限流落地

日期:2026-07-31

一、项目背景

我们网关上线初期用的是固定阈值限流:每秒多少请求、并发多少。看着省事,实际两头不讨好。业务低谷时限流形同虚设,高峰一来要么阈值设太低误伤正常请求,要么设太高没挡住异常流量。最危险的一次,某个调用方因为客户端 bug,发出大量超长 prompt 的畸形请求,底座推理被拖垮,正常业务全跟着超时。我们意识到,固定阈值的限流对大模型场景是"瞎子摸象"——它看不到请求长什么样、底座现在多忙。于是我们做了"实时流量画像 + 异常检测 + 自适应限流"。

二、落地场景

网关现在对每类请求实时画像:请求频率、平均/长尾 token 数、prompt 长度分布、错误率、底座当前负载。异常检测模块基于这些画像识别三类异常:突发尖峰(频率远超基线)、畸形请求(prompt 超长/参数非法)、慢请求风暴(大量长推理占满队列)。识别后不是一刀切,而是自适应限流——对异常来源动态收紧配额,对正常流量保持宽松。同时,限流信号反向驱动底座弹性扩缩容,形成"流量—算力"联动。管控台能看到实时画像和限流动作,运维心里有数。

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

挑战一是实时流量画像与基线。大模型请求差异极大,不能全局一个阈值。我们按"应用+模型+请求类型"建滑动窗口基线,实时更新,异常判定基于偏离度而非固定数。

挑战二是异常模式检测。我们对畸形请求做了轻量规则前置(prompt 长度上限、参数 schema 校验),长尾慢请求靠队列占用时长识别,突发靠频率滚动基线。三层叠加,比单阈值聪明得多。

挑战三是自适应限流阈值与联动。限流不是写死数字,而是"基线 × 系数"动态计算,并对异常来源单独限。关键是限流信号(如队列水位高)反向触发底座扩容,异常退去自动恢复,形成闭环。

四、效果数据

上线后的脱敏示意值:畸形/超长 prompt 类异常请求拦截率约 96%,那类"bug 拖垮底座"的事故实现零复发;正常请求在高峰期的误伤率从固定阈值时代的约 7% 降到约 1.2%;底座因异常流量被打垮的次数从每月约 3 次降到 0;自适应限流生效时延(从识别到收紧)约 2 秒,比人工介入快几个数量级。底座资源在异常期自动扩容,平稳后回收,整体算力成本反而降约 9%。

五、可复用经验总结

大模型网关的限流,必须从"固定阈值"走向"看流量形态"。第一,画像要按业务维度建基线,全局阈值对差异巨大的请求必然误伤或漏防。第二,异常检测比阈值聪明:畸形请求靠前置规则、慢请求靠队列时长、突发靠频率基线,组合识别。第三,限流要自适应(基线×系数),且信号要反向驱动底座扩缩容,这才是流量—算力闭环。第四,限流动作要可观测,运维看不到限流在干嘛,等于没限。我们把这套画像+检测+自适应做成网关内置模块,新接入的应用默认受保护。

结语

固定阈值限流在大模型场景基本是瞎子摸象——它看不到请求长什么样、底座现在多忙。我们那次被畸形请求拖垮底座的事故,根因就是阈值既误伤正常流量、又漏防异常流量。换成"看流量形态"的自适应限流后,这类事故直接归零。

画像要按业务维度建基线,全局阈值对差异巨大的请求必然两头不讨好。我们按应用、模型、请求类型建滑动窗口基线,异常判定基于偏离度。畸形请求靠前置规则、慢请求靠队列时长、突发靠频率基线,三层叠加比单阈值聪明得多。

限流要自适应,且信号要反向驱动底座扩缩容,这才是流量—算力闭环。我们让限流配额随基线动态计算,对异常来源单独收紧,同时把队列水位高这类信号喂给底座触发扩容,异常退去自动回收,整体算力成本反而降了一截。

限流动作必须可观测,运维看不到限流在干嘛等于没限。我们在管控台把实时画像和限流动作都摊开,哪类请求被收紧、为什么收紧一目了然。这套画像加检测加自适应做成网关内置模块后,新接入的应用默认就受到保护,不必各自造轮子。

我们后来把这套限流和异常检测的经验沉淀进网关默认模板,新接入的应用开箱即受到保护。一个直观的感受是,运维群里关于"又被拖垮"的告警少了一大半,大家终于不用在高峰期盯着仪表盘手抖。自适应限流的本质,是把"人盯阈值"升级成"系统看形态",人退到决策位,系统守住底线,这才是该有的分工。

顺带记一个运维视角的收获。自适应限流上线后,我们逐步把固定阈值的老规则下线,运维终于不用在每次大促前手动调参、提心吊胆。系统根据实时形态自己收放,人只需要在异常持续时介入看一眼。这种从人盯系统到系统守底线、人做决策的转变,是整个网关稳定性提升的关键,也比任何单点优化都更可持续。

案例片段(已脱敏): ```

自适应限流与异常拦截(伪代码节选)

profile = sliding_window(app, model, req_type)  # 实时流量画像 baseline = profile.freq_median if req.prompt_len > MAX_LEN or not valid_schema(req):    return REJECT_MALFORMED                  # 畸形请求前置拦截 if profile.freq > 5 * baseline:              # 突发尖峰    quota = baseline * 1.5                    # 动态收紧 signal_queue_high(profile.queue_water)       # 反向驱动底座扩容 else:    quota = baseline * 3                      # 正常流量宽松 apply_ratelimit(app, quota) ``` 限流信号反向触发底座弹性扩缩容,形成流量—算力联动闭环。