跳转至

限流比降 10 倍:百炼网关如何用 RocketMQ LiteTopic 重构大模型限流

Ch01.536 限流比降 10 倍:百炼网关如何用 RocketMQ LiteTopic 重构大模型限流

📊 Level ⭐⭐ | 12.0KB | entities/百炼网关-rocketmq-litetopic-大模型限流重构.md

百炼网关限流重构:RocketMQ LiteTopic 把漏桶变成分布式基础设施

百炼是阿里云的大模型服务平台,承载百万级用户同时调用千问等数十种大模型,作为国内最大的公有云模型推理入口之一,每天处理海量异构推理请求。每一次限流误判意味着用户侧超时、重试甚至业务中断;每一次过载放行意味着稀缺 GPU 算力的浪费和其他租户体验劣化。当平台用户从千级增长到百万级,限流系统面临的已不再是"防刷"这种老问题,而是"如何在有限 GPU 池中实现百万租户各自独立、按需弹性的精细化流量治理"。百炼网关团队用 RocketMQ LiteTopic 做端到端重构,方案上线后限流比降低 10 倍,限流导致的用户可感知异常大幅收敛。

大模型时代限流从粗放走向精细化:GPU 扩容周期长、单价高,供给受制于硬件交付节奏,"GPU 池子有多大"几乎直接决定能服务多少客户、能承诺多高 SLA。百炼网关要在有限 GPU 池里同时兑现三件事:租户级流量隔离(各租户请求相互隔离,防止资源争抢)、精细化配额限流(租户维度差异化配额,仅对超额请求限流退避)、平滑突发与资源统筹(流量整形削峰填谷,低抖动)。传统"一个限流器卡在网关上"的范式已经不够用,团队对限流算法到底层消息队列做了一次端到端重构,把 RocketMQ LiteTopic 作为漏桶(Leaky Bucket)的物理载体。

为什么传统限流模式不够用

百炼面对三类叠加场景:基于 SLA 承诺的基础限流(稳定、可计量、可观测);用户之间及客户内部多账号的细粒度管控(User + Model 维度交叉约束);超大客户的扩容与突发承接(额度调大后突发一来,GPU 扩容到位前硬限会大面积 503、放过去又让 GPU 过载殃及其他租户)。三者交织意味着限流不只是"决定放不放过",更要回答"放过去之后以什么节奏喂给后端"。算法最终选定固定窗口 + 漏桶:固定窗口而非滑动窗口(对短期波动更宽容);漏桶而非令牌桶(漏桶"匀速放行"契合 GPU 这种稳态友好、尖峰敏感的下游,令牌桶天然允许突发,恰恰是 GPU 最怕的形态)。

方案选定后新问题出现:超大客户突发流量堆在网关进程内存里,几十万请求会立刻把网关本身打挂。漏桶必须从进程内搬到进程外,用一个足够大、足够隔离的外部存储承接缓冲,把"接住请求"和"按节奏放行"在物理上拆开——这是 LiteTopic 进入视野的起点。

传统 Topic/Group 撑不起平台级漏桶

最初落地是为每个 User + Model 单独建 Topic 与 Consumer Group,再部署一组消费机器专门负责该链路,但三个痛点很快暴露:元数据重、生效慢(传统 Topic/Group 需预先创建,生效时间几十秒量级,新用户突发流量到来时出现短时异常);机器利用率低、成本随客户数膨胀(共享消费模型要求同一 Consumer Group 订阅完全相同的 Topic 集合,否则订阅不一致导致堆积甚至丢失;要隔离客户流量就必须每个客户单独建 Group 甚至切机器,哪怕客户一条消息都没有,名下机器仍要常驻);单 Topic 暴涨的株连效应(硬把多客户数据塞进同一 Topic,某个用户消息激增时几乎所有消费线程被占据,其他用户全部被阻塞)。团队最终不得不退回"一客户一组机器",用机器规模换隔离强度。传统方案能服务少数几个头部突发客户,但无法支撑任意中大型客户自动接入漏桶——当限流要从"个别 VIP 待遇"变成"平台基础能力",底层架构必须重新设计。

LiteTopic 三件套与分布式漏桶矩阵

LiteTopic 是 RocketMQ 5.x 引入的轻量级队列形态,与传统 Topic 的三个关键差异正好对应三个痛点:轻量元数据(单 Broker 支撑百万级 LiteTopic,运行时按需创建、按 TTL 自动回收,客户端往不存在的 LiteTopic 发消息即自动建出);差异化订阅(同一 Consumer Group 下不同消费实例可订阅不同 LiteTopic 子集且不引发堆积或丢失,订阅关系从"刚性约束"变成"按需路由");Suspend 消费控制(消费回调中返回 Suspend N 毫秒,Broker 暂停对该 LiteTopic 的拉取,不影响其他 LiteTopic——这是漏桶在 Broker 层落地的关键开关)。

重构后的架构:发送侧通过基础限流校验后按 User + Model 写入对应 LiteTopic,User 与 Model 信息直接编进名字,天然多租户物理隔离;消费侧把原来按客户切分的几十组机器合并为统一一组 Pod,通配符订阅全部 LiteTopic,新增客户时发送侧自动建、消费侧自动拉,无需改代码、无需重启、无需扩机器;限流逻辑收敛到消费线程内几行判断——命中则返回 Suspend N,否则转发模型并 ACK。这套机制可以理解为分布式漏桶矩阵:每个 User + Model 拥有一个独立漏桶,桶容量由 LiteTopic 堆积上限与 TTL 决定,出水速率由消费侧 Suspend 时长动态决定;整个矩阵共享同一组消费机器,资源池随总流量伸缩,而非按客户数线性增长。

LiteTopic 为何是漏桶的天然载体,三个维度恰好对上"GPU 稀缺 + 多租户 + 突发尖峰":桶容量工程意义上近似无限(数据持久化到 Broker 磁盘,单实例承载百万级队列,堆积上限远超进程内队列且彼此物理隔离,"等几秒再处理"几乎在所有场景下都优于"被 429");每个 User + Model 各拥有独立漏桶(租户隔离变成命名规则问题,客户 A 的 Model X 进 liteTopic-A-X,客户 B 的进 liteTopic-B-X,桶与桶在 Broker 层物理隔离,A 链路堵了不会通过共享资源传染到 B);每个漏桶速率可独立、动态调整(Suspend N 完全由业务策略实时计算,毫秒级调整任意漏桶放行速度:重要客户在负载高时仍拿较高节奏、模型扩容后矩阵速率同步上调、某模型拥塞单独收紧对应列,不重启消费组、不改配置、不需要客户感知)。核心改动可浓缩成三段代码:发送侧 msg.setLiteTopic(buildLiteTopicName(user, model));消费侧 consumer.subscribe("bailian-rate-limit-parent", "*") 通配符订阅;限流逻辑消费回调里 rateLimitPolicy.acquireOrSuspend(liteTopic) 命中则返回 Suspend

关键工程技术细节

海量 LiteTopic 消费性能:几十万 User + Model 并发是日常态,若沿用"对每个订阅的 LiteTopic 各发起独立 Pull 循环"的传统做法,开销随订阅数线性增长(类似 select/poll 每次遍历全量集合)。LiteTopic 在 Broker 侧引入就绪集合(Ready Set)事件驱动机制,思路类似 epoll:只有真正有新消息写入的 LiteTopic 才进入就绪集合,Pull 时只读取就绪 LiteTopic,集合为空则长轮询等待事件触发。Pull 开销只与"当前时刻就绪的 LiteTopic 数量"成正比而非总订阅数。POC 压测中,单 Broker 承载 200 客户端 × 1 万 LiteTopic(共 200 万队列),平均消费延迟稳定在 12ms;同等订阅量下传统逐 Topic 轮询,消息稀疏时 CPU 高出数倍且随订阅数恶化。

Suspend 精度与线程公平性:Suspend 当前最小粒度 30ms,更细的速率控制需要消费侧局部 Sleep;若业务目标速率非常高,要把 Suspend 步长和并发线程数放在一起算实际放行速率,避免阶梯感传导到 P99 RT。多租户共享消费组下所有 LiteTopic 共用同一线程池(POC 中 50 线程),限流方式直接决定其他 LiteTopic 是否被"误伤":POC 对比订阅 50 个 LiteTopic、前 5 个随机触发 300ms 限流——Thread.sleep(300) 时被限流的 LiteTopic 各占住一个线程不释放,被限流数增至 40 个时线程池几乎耗尽,剩下 10 个正常 LiteTopic 全部堆积,限流"传染"到不该被限流的租户;Suspend 300 时消费线程立即释放回线程池转头服务其他 LiteTopic,被 Suspend 的由 Broker 在 N 毫秒后重投,结果仅被限流的 5 个堆积、其余 45 个正常。本质区别:Sleep 是线程级阻塞会通过共享线程池扩散,Suspend 是 Broker 级拉取流控与其他漏桶在线程层面完全解耦。

经验总结与可复用范式

几条经验:限流不是单一算法而是分层组合——固定窗口管硬上限、漏桶管放行节奏、消息队列管承接缓冲,三层串联缺一不可;漏桶的物理载体决定上限——额度大到突发可能压垮网关进程时,漏桶必须从进程内搬到进程外,MQ 是天然候选,但要追问能否支持百万级队列、能否运行时按需创建、流控粒度是否够细;LLM 场景对租户隔离要求更高,但隔离成本必须更低——大模型推理一次请求消耗数秒 GPU 时间,被挤占损失的不只是成功率还有已消耗的昂贵算力,靠"每租户切一组独立机器"成本随客户数乘法膨胀,LiteTopic 让隔离强度不降、成本从乘法变回加法;Suspend 与 Sleep 各有适用场景,关键在于谁为等待买单——Suspend 适合粗粒度长时间限流等待,Sleep 适合亚毫秒级节奏控制的短时补充,百炼实际是两者组合。

从业务结果看,LiteTopic 提供的"轻量队列 + 差异化订阅 + Suspend 控速"三件套让百炼网关限流比降低 10 倍。这套方案并非百炼独有:任何大模型平台或推理服务只要面对"GPU 稀缺 + 海量租户 + 突发尖峰"三个约束都会遇到同样困境,百万级物理隔离队列 + 动态速率调度 + 零运维弹性是一套可直接复用的基础设施范式。大模型时代,限流不再是一道防御题,而是一道资源调度题——当 GPU 成为最稀缺的生产要素,谁能把有限算力更精细、更公平、更弹性地分配给每个租户,谁就能在体验和成本之间找到最优解。

相关

原文存档