日期:2026-08-01
我们自托管了一套大模型推理服务,多副本横向部署扛并发。起初请求用最简单的轮询分发,问题很快暴露:一是 KV 缓存命中低,同一会话的后续请求被打到不同副本,上下文反复重算;二是长会话和多轮对话的上下文在副本间无法复用,GPU 白烧;三是副本负载倾斜,有的副本排长队、有的在摸鱼。结果 GPU 利用率上不去,尾延迟(P99)却居高不下,业务方抱怨"有时快有时卡"。
我们在推理接入层加了一层亲和路由。每个会话/用户带稳定路由键,请求按一致性哈希落到固定副本,会话内的 KV 缓存得以复用。同时做副本健康探测,给每个副本打健康分(延迟、排队、显存),路由时避开亚健康实例。当某副本持续过热,触发再均衡把部分会话迁移走。管控台有副本负载热力图和 KV 命中率曲线。
挑战一是请求亲和与 KV 复用。我们给请求注入路由键(会话 id 或用户 id),一致性哈希映射到副本,同会话连续请求命中同一副本的 prefix cache,首字之后延迟明显下降。
挑战二是副本健康探测与打分。光看 CPU 没用,我们探的是推理特有的指标:排队深度、显存碎片率、最近 N 次 P99。打分低于阈值就从路由表摘除,恢复健康再回切。
挑战三是负载倾斜再均衡与亲和失效。副本扩缩容会改变哈希环,我们用带虚拟节点的环并做平滑迁移,避免大规模会话抖动;迁移时把源副本的缓存预热到目标,缩短冷启动。
约二十副本集群的脱敏示意值:同会话 KV 缓存命中率从约 22% 提升到约 68%,多轮对话平均时延下降约 41%;副本负载方差(按 QPS 算)从约 0.38 降到约 0.09,倾斜基本消失;P99 时延从约 3.8 秒降到约 1.6 秒;GPU 平均利用率从约 54% 提升到约 81%,同等流量下副本数可缩减约 20%。
第一,推理负载均衡不能只轮询,请求亲和能直接把 KV 缓存复用率拉起来,这是性价比最高的优化。第二,副本健康要看推理特有指标(排队、显存碎片、P99),通用指标会骗人。第三,再均衡用带虚拟节点的一致性哈希 + 缓存预热,扩容不引发会话风暴。我们把亲和路由与健康探测抽成通用件,新模型接入主要配路由键与探测项。
推理服务和普通 Web 服务最大的不同,在于 KV 缓存是命根子。轮询看着公平,实则把同一会话的后续请求打散,上下文反复重算,GPU 干了大量重复活。加上亲和路由、按会话固定副本后,prefix cache 复用率直接从两成出头窜到近七成,多轮对话的体感立竿见影。
健康探测别只看 CPU。推理副本的"病"在排队深度、显存碎片、P99 抖动,这些才决定请求会不会被拖死。我们给副本打健康分,亚健康的直接摘出路由,恢复再平滑回切。再均衡最怕扩容引发会话大迁移,用带虚拟节点的一致性哈希加缓存预热,迁移是平滑的、冷启动是短的。这套路由能力抽成通用件后,新模型上线只配路由键和探测项,弹性扩缩不再阵痛。
案例片段(已脱敏): ```
一致性哈希亲和路由(伪代码节选)
ring = ConsistentHash(replicas=128) # 带虚拟节点 ring.add(replicas_health) # 按健康分加权 node = ring.get(key=session_id) # 会话级亲和 if node.health_score < 0.5: node = ring.next_healthy(session_id)
副本扩缩:仅迁移受影响虚拟节点,源缓存预热到目标
for vn in changed_vnodes: migrate_cache(vn, warm=True) ``` 会话级亲和复用 KV;虚拟节点哈希平滑迁移。
亲和路由上线后,我们还顺手解决了一个老大难:长文档问答的首字延迟。多轮对话里用户常引用前文,亲和让上下文复用,首字之后几乎无等待。业务方原话是终于不卡了。这说明推理优化里,缓存复用的杠杆常常比堆机器大得多。再均衡也让我们重新认识了扩容。过去扩容要挑凌晨、停写、迁数据,运维提心吊胆。现在双写加增量追平,白天也能扩,流量灰度切,业务零感知。我们甚至把扩缩容接进底座监控,副本持续过热就自动加节点。推理服务的弹性,从此不是应急预案,而是日常能力。
给推理平台的提醒:亲和路由的路由键选型很关键。我们最早用用户 id 做键,发现同一用户多端并发时副本还是会被打散;后来改成会话 id,多轮对话的复用率才真正起来。路由键要和你最想复用的上下文对齐,不是随便挑个 id。再平衡也别太激进。我们设了负载分阈值和冷却时间,避免副本刚热就被迁、刚迁又热,来回抖动。弹性是慢工夫,阈值和冷却调稳了,扩容才舒服。推理服务的稳定性,很多时候是这些细节堆出来的。
KV 缓存我们做了分层。prefix cache 放热点会话、最近 N 轮放短时缓存,冷会话不占资源。分层后缓存命中率更准,显存也更省。缓存不是越大越好,是越准越好。健康探测的阈值我们也调过几轮。最初只看 P99,发现偶发长请求就把副本摘了,误摘多;后来加排队深度和显存碎片做综合分,摘除更准。探测指标选错,路由反而添乱。副本扩缩我们接了底座的弹性信号。副本持续过热,不只是再均衡,还触发加节点;副本长期空闲,回收省成本。推理服务的弹性,是路由层和底座一起完成的,单靠一层不够。最后一句话:推理优化里,亲和路由是性价比最高的一招。它不花一分钱买机器,只是让请求落在对的地方,KV 复用和尾延迟就同时好转。很多性能问题,是调度问题,不是算力问题。