ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI推理网关实战:从负载均衡到推理感知的路由架构与策略

AI推理网关实战:从负载均衡到推理感知的路由架构与策略 把大模型推理服务真正推到生产环境之后最先发现的一个尴尬事实是模型跑得动流量却管不住。我之前部署过一套基于vLLM的服务多个模型、多个副本挂在集群里前端只放了一个常规Nginx做负载均衡结果线上并发一上来问题全暴露了——某个实例的GPU显存被大请求打满另一个实例却闲着流式输出的长连接把并发窗口占住短请求反而排队排到超时更头疼的是模型滚动更新时只能手动切换流量稍有不慎就是一片告警轰炸。后来我把整个路由层彻底重做核心就是引入了一个专门的AI推理网关把请求从“按连接转发”改成“按推理状态和策略路由”效果立竿见影。这篇文章就把这套AI推理网关的路由架构和策略实践完整拆一遍。我会从推理场景为什么不能用普通网关讲起然后依次梳理路由架构的分层设计、各类路由策略的适用条件和组合方式、典型业务场景下的配置参考最后整理一份排障速查表。内容偏工程落地适合正在做大模型推理服务化、或者在网关选型上犹豫不决的同学。1. 为什么需要AI推理网关一次真实的流量“翻车”复盘先说我踩过的那次事故。当时线上有3个模型每个模型部署了2个vLLM实例前面只用了Nginx做简单的轮询负载均衡。某天下午业务方发起一个营销活动用户请求量涨了大概4倍结果不到十分钟就出现大量超时。查下来原因很典型有一部分用户上传了超长文档单个请求要生成几百个Token这类请求把实例的并发窗口全占满了而Nginx还在把新请求源源不断地送进来排长队。再加上有两条连接在做流式输出连接一直挂着不退Nginx的心跳、负载判定全乱了套。最后只能人工把一部分流量摘掉等高峰过了再恢复。事后复盘问题的根子不在推理引擎而在路由层。通用网关和服务发现机制对推理流量的理解太浅了它以为自己在转发普通的短连接HTTP请求但实际上它面对的是高显存占用、分钟级长连接、有状态缓存的一群异构实例。从这里就能得出结论大模型推理服务化需要一个专门为推理场景设计的中间层也就是AI推理网关。1.1 推理流量与普通Web流量的三个本质差别为什么不能用传统负载均衡硬扛推理流量因为两者的流量模型完全不一样。第一连接时长差异巨大。普通Web请求通常在几百毫秒内结束而一个流式推理请求从建立连接到输出完最后一个Token可能持续30秒甚至几分钟。传统负载均衡的最小连接数、连接复用策略在这种场景下几乎没有意义反而会因为连接长期占用导致误判后端状态。第二资源占用极不对称。普通请求占用的是CPU和内存资源粒度比较统一推理请求占用的是显存和GPU算力而且不同请求差异巨大。同样一个模型一个10个Token的问答请求和一个4096 Token的长文生成请求消耗的算力可能差上百倍。网关如果只按“请求数”做负载均衡本质上就是在闭着眼睛分配资源。第三后端实例不是完全无状态的。推理引擎普遍有KV Cache缓存、前缀缓存Prefix Cache、置信度采样等状态。同一个问题打到不同的实例命中缓存的概率不一样首Token延迟TTFT和生成速度都会差很多。普通网关看不到这些状态也就做不了更聪明的调度。1.2 通用网关做推理路由的四个典型痛点一番实践下来我把通用网关在推理场景的缺陷总结成四点。一是对后端健康状况的判断维度太单一。通用网关只会做连通性探活比如TCP层探活、HTTP Health Check但推理实例是健康还是“忙死”根本看不出来。一个实例GPU利用率已经99%队列里堆了几十个请求网关还是会往里转发新流量。二是对推理引擎协议支持不完整。现在的推理服务大量使用SSE流式响应、WebSocket、gRPC这种长连接型协议通用网关在处理流式转发、流终止、错误响应拼接这些环节上经常出幺蛾子。例如SSE流中间断掉之后网关可能不知道已经结束一直占用着后端连接。三是没有推理上下文概念。路由行为不会考虑模型版本、批处理队列、前缀缓存亲和性、推理超时策略等关键参数这些恰恰是推理性能的命门。四是扩缩容和发版联动困难。模型更新、实例扩缩容的时候通用网关的配置基本靠手工改缺少排空、预热、灰度上线这些机制每一次发版都像在走钢丝。AI推理网关就是为补上这些短板而生的。它的核心职责可以概括为把模型请求按策略分发给最合适的推理实例同时保证流式转发正确、状态感知及时、故障处理可控。2. 路由架构设计把“按请求转发”升级为“按状态调度”我在设计这套推理网关时最先确定的是整体架构不能做成一个大而全的“万能代理”而是要把路由能力拆成清晰的分层。每个层各司其职出了问题也容易定位。2.1 数据平面与控制平面的分工整个网关架构我按数据平面和控制平面来切分这是很多后端系统的通用思路在推理场景里也成立。控制平面负责路由规则、模型版本、权重配置、健康检查结果和扩缩容策略的管理。它不直接接触请求流量只做“决策”。比如新上了一个模型版本控制平面会先把新实例注册到路由表里标记为“预热中”状态等待它完成加载并准备好缓存再逐步把流量切进去。数据平面负责实际的请求代理和转发。它接收客户端的推理请求查询路由表执行路由策略把请求转发到后端推理实例同时负责流式数据的双向转发。数据平面要求性能和稳定性都足够硬因为在推流场景下一条链路要持续占用很久任何一条TCP连接的异常都会直接对业务造成影响。在实现上这两个平面可以放在同一进程里也可以拆成不同的服务。小规模场景放同一进程更省事但一旦要支持十几个模型、几十个实例我建议至少把控制平面的路由规则外置到配置中心数据平面只保留一个轻量的规则缓存这样改策略不需要重启网关。2.2 路由表与实例抽象模型路由架构里最重要的数据结构是路由表。它不是一张简单的“域名到IP”映射表而是一个多层的模型描述。我习惯把路由表设计成两层一层是模型层一层是实例层。模型层以模型名称为主键记录这个模型支持的路由策略、默认超时时间、是否需要前缀缓存亲和性以及可用的版本列表。实例层描述的是某个模型版本下的具体推理实例包括实例ID、地址、健康状态、并发窗口容量、当前队列深度、平均首Token延迟、KV Cache命中率等运行时指标。有了这个抽象模型路由决策就变成了一个两步过程先根据请求的模型名找到对应的模型层路由规则再根据实例层的实时指标从候选实例列表中选出最佳的那个。2.3 网关与推理引擎之间到底要感知什么网关对推理引擎的“感知能力”直接决定了路由策略的上限。我梳理了三个必须感知的关键状态。第一个是队列深度。推理引擎通常有一个调度队列请求进来后不会立刻执行而是先排队等GPU资源。队列深度是比GPU利用率更精确的负载指标。一个实例GPU利用率高不一定服务慢队列深度大才是真的危险信号。网关应该定期比如每1-2秒从推理引擎拉取或被动接收队列深度指标低于阈值的实例优先接流量。第二个是批处理状态。现代推理引擎支持动态批处理多个请求可以在同一个推理步骤里合并计算。这意味着“正在执行中的请求数”不等于“真的在占资源的请求数”网关如果只看连接数或请求数会严重误判。比较好的做法是让推理引擎把自己当前的调度批次大小、有效Token吞吐量实时上报给网关。第三个是缓存状态。KV Cache的前缀缓存命中率对推理延迟影响巨大。命中缓存的请求可能只需几十毫秒就能吐第一个Token未命中的请求可能要等几百毫秒甚至更久。网关在做路由时如果能感知到哪个实例缓存了哪些前缀就能大幅提高命中率。关于第三点后面的路由策略章节我还会单独展开。3. 路由策略实践从轮询到推理感知的精细化调度路由策略是推理网关的核心竞争力。我个人把策略分成了四个层次基础策略、感知型策略、缓存亲和性策略、多目标组合策略。实际生产环境基本不会只用一种策略而是按业务需求组合出最合适的调度逻辑。3.1 基础路由策略轮询、哈希、最小连接数够用吗先说结论小规模、低并发场景下够用生产环境并发一大就明显捉襟见肘。轮询Round Robin实现最简单请求按顺序循环分发到各个实例。缺点是完全没有负载概念实例之间配置不一样、状态不一样时慢实例会拖慢整体性能。加权轮询可以稍微缓解权重靠人肉调实例状态一变又失真。一致性哈希的作用是保证相同特征的请求总是路由到同一个实例提高缓存亲和性。它的好处是实现简单、无额外指标依赖缺陷也很明显一旦实例扩缩容哈希环上的映射关系会大规模变化缓存命中率反而可能出现抖动。而且哈希路由完全不看实例负载容易出现热点实例被哈希流量打爆的情况。最小连接数比轮询进了一步能感知连接数但刚才说过推理场景的一条连接和另一条连接的资源消耗可能差一个量级。两个实例连接数相同一个在跑512 Token的长文生成一个在跑10 Token的快速问答负载完全不一样。所以最小连接数在推理网关里只能作为辅助信号。我自己在做网关接入的初期用的是加权轮询最小连接数的组合并发量几百的时候还算稳定但是业务量一上来、请求长度方差变大之后这套组合就彻底顶不住了被迫升级到感知型策略。3.2 推理感知策略队列深度、实时延迟与吞吐感知感知型策略的核心思路是把推理引擎的实时运行状态引入路由决策让流量流向真正“有余力”的实例。队列深度感知是我最推荐优先落地的策略。网关持续获取每个实例的排队请求数决策时优先选择队列最浅的实例。这个策略实现成本低效果显著尤其适合vLLM这类有明确并发窗口的推理引擎。要注意的是队列深度指标需要平滑处理否则实例的队列在快速波动时会导致流量来回抖动。延迟感知策略是选择平均首Token延迟最低的实例。这里的延迟数据要区分统计窗口建议同时维护1分钟和5分钟两个口径短窗口用于捕捉瞬时异常长窗口用于反映稳态性能。实际使用时可以做成“短窗口为主、长窗口兜底”的加权评分。吞吐感知策略适合跑高并发在线场景。它可以监控每个实例的实际Token生成速率选择吞吐余量最大的实例。但这个策略对指标质量要求很高如果推理引擎的指标上报不规律吞吐数据的噪声会很大反而把路由搞乱。我实际落地时的建议是从“队列深度 延迟”组合开始跑稳定后再引入吞吐感知。优先保证稳定性而不是一步到位追求最复杂策略。3.3 KV Cache亲和性路由容易被忽略的缓存命中率这个策略我觉得是最有推理场景特色、也最容易被忽略的一环。现在主流的推理引擎比如vLLM都支持Prefix Caching自动前缀缓存或者RadixAttention这类机制。简单说如果请求的Prompt前缀在某个实例的KV Cache里命中过引擎可以直接跳过一部分Prefill计算第一个Token的生成速度会快非常多。可如果网关把请求随机分发到不同实例每次前缀都大概率不命中等于白白浪费了缓存能力。我的解决方案是引入“亲和性路由”网关在做路由决策时会把缓存亲和性作为一个评分维度。具体实现上分两级。第一级是针对系统Prompt完全固定的场景比如客服机器人总是在Prompt前面拼一大段固定的角色设定和知识库引导这种情况直接按请求特征做一致性哈希保证同一个用户或同一个业务线的请求尽量落在同一个实例上。第二级是接入推理引擎的缓存状态接口让引擎在网关上报当前缓存的前缀Key、命中次数、最近命中时间网关根据这些信息实时调整实例评分。这里有一个很现实的权衡缓存亲和性越强负载均衡的自由度就越低容易出现某个实例因为缓存命中最多而流量越来越集中的情况。我的处理办法是给缓存亲和性设一个“权重区间”比如让它占路由总评分的30%其他正常负载指标占70%。这样既能吃到缓存红利又不至于让负载失衡。3.4 多目标与多租户策略组合生产环境里网关往往同时服务多个业务部门、多个模型路由策略不能只有一个维度。我常用的做法是把路由评分拆成三块基础健康分、负载得分、业务约束分。健康分决定候选实例池不健康的实例直接踢出候选池负载得分决定实例间怎么分配流量业务约束分处理租户隔离、优先级配额、成本控制这些额外要求。在支持多租户的场景下还要考虑配额和优先级。有的业务线是核心链路必须保证低延迟有的是离线分析任务可以有较高的延迟容忍度。网关里可以为不同租户配置并发配额和优先级队列高优先级租户的请求即使排在后面也能通过抢占或跳过低优先级请求的方式加速处理。成本控制也是一部分。如果多个模型可以共享GPU资源网关可以通过路由策略把某些低峰期的请求调度到资源更空闲的实例上减少碎片化占卡。这类策略一般做成定时或事件驱动的动态权重而不是静态配置。4. 典型场景的策略组合与配置参考理论讲完了说点能直接抄作业的。我整理了四类常见业务场景每个场景给出策略组合和关键配置思路。4.1 通用问答/客服场景延迟优先这类场景的特点是单个请求通常较短用户非常在意首Token延迟。业务方要求TTFT控制在1秒以内整体响应时间不能超过10秒。路由策略组合我建议为队列深度感知 延迟感知 轻量缓存亲和性。具体配置上候选实例的队列深度阈值设为最大并发窗口的50%以上直接降权或摘除延迟指标采用1分钟短窗口平均阈值设为目标TTFT的80%作为警告线。缓存亲和性只对System Prompt非常固定的请求启用不必对所有请求强绑。超时设置上首Token超时建议设为3秒超过即触发重试或降级总超时按业务要求设置一般10-15秒即可。这类场景重试需格外谨慎因为重复生成会产生额外Token消费成本重试前要确认请求是幂等的或者业务侧能够接受重复生成的结果。4.2 代码生成/长文档处理吞吐优先这类场景请求头很长生成长度也大资源消耗高用户对首Token延迟相对宽容但对总耗时和稳定性更敏感。策略组合为吞吐感知 队列深度感知 前缀缓存强亲和。配置关键点在于要放宽对候选实例的队列深度限制否则大部分实例都会被摘除导致流量集中在少数实例上。我建议把队列深度阈值设定为“最大并发窗口×80%”同时引入“最大排队时长”概念排队超过5秒的请求直接返回错误而不是无限等待。缓存亲和性这里要重点开。代码生成场景的系统Prompt和文件前缀往往高度重复一次缓存命中能省掉一大半Prefill开销。建议网关和推理引擎配合把命中率这个指标也纳入路由评分至于权重可以稍微调高到40%左右因为这类请求的缓存收益实在太明显。4.3 多租户混合负载配额与优先级隔离这种场景最常见业务线A做实时助手业务线B做批量文档分析两张卡混在一起跑。策略组合为多目标评分 优先级队列 租户级并发配额。操作时我先按业务线给不同租户建立独立的虚拟路由空间相当于在网关内部做了一层轻量级租户隔离。每个租户有独立的并发配额比如A业务线峰值并发50B业务线峰值并发200配额用令牌桶控制超出的请求直接排队不允许抢占其他租户的配额。除了并发配额优先级也要分层。高优先级请求可以跳过低优先级请求的排队位置但不能无限抢占否则低优先级业务会被饿死。我的做法是给低优先级租户设置最小保证并发数即使高峰时期也要保留20%的调度能力给它。4.4 模型灰度发布与滚动更新最后一个场景非常体现网关的工程价值。模型几乎每周都要更新直接全量上线风险太大必须走灰度。网关在这个过程里承担三个角色流量灰度控制器、实例排空执行器、以及上线失败的回滚开关。灰度策略我习惯用“权重灰度金丝雀验证”的组合新版本先挂一个金丝雀实例网关配置5%权重把一部分流量导进去配合自动化指标对比比如首Token延迟、生成质量分数、报错率。对比通过后再逐步把权重提高到20%、50%、100%。滚动更新时最重要的是“实例排空”。网关要把待下线实例标记为“排空中”停止给它分发新请求同时允许已经建立的长连接继续跑完等所有流式请求结束后再真正销毁实例。这个机制能避免用户在生成到一半时断流。我之前没做排空时吃过亏模型更新期间一堆用户反馈“生成到50%突然断了”后来加上排空逻辑问题直接清零。5. 落地细节超时、重试、熔断与可观测性路由策略能跑通并不等于生产环境能稳定运行。真正决定网关工程质量的是超时、重试、熔断这些防御机制的设计还有可观测性建设。这一章我讲几个落地时最容易被忽视的细节。5.1 超时与重试的粒度控制推理请求的超时必须拆成两段看首Token超时和总生成超时。两者含义完全不一样。首Token超时指的是请求发到后端后到收到第一个响应Token的最大等待时间。它反映了Prefill和后端调度速度。这个值设太短碰到短时负载抖动就会误杀请求设太长用户会发现页面一直转圈没办法给出反馈。我一般建议根据业务可容忍TTFT设置通常3-5秒。总生成超时则根据模型和场景差异很大。一个内容生成长度上限为2048 Token的模型如果生成速度是50 Token/s总耗时至少要预留45秒以上。实际配置里建议给模型参数中的max_tokens留出1.5倍余量避免因为偶发慢Token导致超时。重试比超时更容易踩坑。推理请求重试有不小概率会造成重复扣费和使用量翻倍。我在网关里做的处理是只对“连接失败”“实例不可达”“明确返回的瞬时错误”这几种情况自动重试像“收到部分Token后连接断开”这种基本不自动重试而是让客户端或业务系统去判断要不要重新发起。重试次数限制为1次同时要求重试请求携带原始请求的幂等键方便计费系统去重。5.2 熔断与降级策略怎么设网关的熔断策略不能照搬普通微服务的阈值。普通服务熔断看错误率和超时率推理网关还要额外看队列深度和平均排队时间。我在实践中使用的熔断规则是双阈值触发实例级熔断实例的错误率连续2分钟超过10%或平均队列深度连续超过最大并发窗口的90%则从候选实例池中摘除熔断时间3分钟。模型级熔断某个模型的所有实例都忙不过来或者整体错误率超过30%网关直接对该模型返回503快速失败避免所有请求都卡在队列里把网关自身拖死。降级策略也要提前设计。常见做法是设置一个兜底小模型比如主模型超时后自动切到快速模型或者开启“结果截断”模式超时依然返回当前已生成的Token而不是报错。这类降级会影响生成质量需要和业务方提前对齐。5.3 路由维度指标建设一个推理网关如果不可观测等于没有生产准入资格。我在搭建指标的时候除了常规的请求数、延迟、错误率之外额外加了四个路由专属指标。第一个是路由决策分布记录流量最终分发到哪些实例和模型版本过滤维度包含平台、租户、用户ID、模型名。第二个是后端实例状态快照包含每个实例的队列深度、GPU利用率、Token生成速率、缓存命中率按时间序列存储排查问题时能回放到实例的实时状态。第三个是策略命中统计比如KV Cache亲和性命中率、熔断触发次数、配额拦截次数这些指标能直接反映路由策略是否按预期工作。第四个是上游等待分解指标。将总延迟拆分为“网关转发耗时”“后端排队耗时”“后端生成耗时”快速定位延迟瓶颈在网关侧还是推理引擎侧。这一块建议直接用Prometheus Grafana这套组合标注好指标体系后再配合告警规则比如TTFT P99超过2秒持续5分钟就告警。没有监控的网关上线之后就是盲人骑瞎马。6. 常见问题与排查技巧实录这一节把我这几年和推理网关打交道时遇到的典型问题整理成一张速查表每一条都是真实踩过坑的。现象可能原因排查方法解决方案部分实例GPU跑满、其他实例空闲路由没启用负载感知只用轮询或哈希看网关路由决策分布和后端队列深度指标启用队列深度延迟感知组合策略流式生成中途断开后端滚动更新时没有排空实例被直接销毁查看网关日志确认断开前是否发生过实例下线为滚动更新加排空机制标记为排空中不再分发新请求首Token延迟突增但GPU利用率不高请求排队严重队列深度没进路由决策查看后端实例的排队等待时长分布引入队列深度感知对超长请求做并发限制模型升级后部分请求结果异常灰度权重配置错误新旧版本同时服务同一类请求且没有隔离检查灰度路由规则对比新旧版本的请求Sampling参数基于模型版本做路由匹配新版本先小流量跑金丝雀重试导致Token消耗成倍增加网关把流式断连请求也自动重试了检查Token计费日志中的重复请求只对连接失败类错误重试同时带幂等键去重缓存命中率一直上不去哈希路由扩缩容导致实例映射频繁变化观察路由前后同一前缀请求的命中率差异启用缓存亲和性评分或改用按固定前缀分组路由高优先级业务反而比低优先级慢优先级抢占没有最小保证被高并发业务拖垮查看各租户的排队时间和调度次数给高优先级业务设置最大配额保障低优先级最低并发实现分层调度网关自身CPU/内存被打满长连接数量过多连接池没有得到有效复用或释放监控网关的连接数和内存走势对空闲连接设置回收时间流式请求结束后及时释放池化连接排查这类问题我的习惯是“先看指标再看日志最后才动配置”。很多问题表面上是路由规则不对实际根因是实例状态上报延迟或者配置下发不一致。碰到这类问题第一步是确认控制平面的状态是否和数据平面的实际情况同步很多时候重启配置同步就能解决80%的烦恼。7. 实际踩坑后的几点体会最后聊几句实在话。AI推理网关这套体系我在业务发展到一定规模之前是完全没意识到的。那时候总觉得大模型应用的核心在模型本身后来才发现当模型部署到多实例、多版本、多租户之后路由调度对整体体验和成本的影响一点都不比模型调参小。我个人实际过程中的一个体会是不要一上来就追求“最智能的路由算法”。推理网关的路由策略从轮询升级到感知型其实并不难难的是把基础问题先解决好——让实例的健康状态准确、让指标上报稳定、让流式转发不出错。地基不稳再花哨的调度算法也是空中楼阁。另外一个深刻的教训是网关和推理引擎的联动一定要提前规划不要把网关当成一个完全独立的中间件。选型或自研的时候就要想清楚网关能不能拿到队列深度、缓存状态这些关键指标能拿到什么级别这决定了后续路由策略的上限。这篇文章把这套路由架构和策略实践整理出来也是希望正在搭推理服务层的同学少走一点弯路。有条件的话建议先用两三个模型小规模试一试队列深度感知和缓存亲和这两个策略效果往往比你预想的明显。后面如果有机会我再写一篇关于推理网关在流式转发和协议适配上的细节那又是一整块值得展开的坑。
返回列表