服务限流实战
5 min
设想有这样一个场景,我在我的 UGC 平台接入了一个评论机器人,用户在其他用户的评论区可以通过 @robot 来触发回复。由于我的机器人回复是使用第三方 API,如 OpenRouter,来实现个性化 LLM 回复的,因此这里涉及到限流的问题。
瓶颈

- 第一个是用户请求层面的,我们不能无限制地纵容用户一直调用机器人评论服务。
- 在功能层面,我们可以限制用户单位时间内的调用次数,比如使用 Redis 记录每分钟调用次数不能超过 5 次。
- 在技术层面,若已经在功能层面进行限制了,但是用户基数非常大,实际上仍旧有很大规模的用户在调用这个服务,我们可以使用 MQ 或者令牌桶来进行限流。
- 第二个是 LLM 服务端的流量限制。
- LLM 服务端如 OpenRouter,对单个用户的请求会有 RPM/TPM 限制,这属于外部瓶颈。
- 可以使用 MQ + 令牌桶做流量整形,以及加上熔断策略。
- 第三个是 LLM 返回信息给我们,但是我们写入评论服务流量太大,单个线程可能也来不及处理,因此我们可以使用线程池来并行写入,同时也可以使用 MQ 来削峰填谷。
限流和熔断
首先明确这两个概念:
限流:是限制系统的请求频率或内部某些功能的执行频率,防止突发的流量激增导致整个系统不可用,常见的 限流算法 有滑动窗口、漏桶、令牌桶等。
熔断:当调用外部服务、数据库或微服务时,如果连续出现失败、超时或响应过慢,熔断机制会“断开电路”,暂时中止调用该依赖。在熔断开启期间,系统直接返回错误或降级结果,不再继续发请求。等一段“冷却时间”后,再少量放行测试请求;如果恢复正常,熔断自动关闭。
熔断特性
- 慢调用熔断
- 异常比例熔断
- 半开状态试探
针对上一节提到的三个瓶颈,针对用户请求层面上的,我们主要使用限流策略;针对调用下游 LLM 服务的,我们主要使用熔断策略;针对回写数据库这里属于内部 IO,可以使用 MQ 做异步来进行削峰填谷。
实战
计划
第一部分分为业务和技术两类限流。
- 业务限流:
- 限制每人每分钟请求次数不超过 5 次
- 限制每人每天请求次数不超过 20 次
- key 设计
- 每次请求需消耗一个金币,金币不足不能被请求
- 技术限流:
- 使用令牌桶算法,限制总体 QPS 不超过 100
第二部分为调用 LLM 外部服务,主要设计熔断策略。
- 要求
- 如果返回大于 60s 就熔断
- 如果异常比例大于 50% 就熔断
- 熔断时间过后,拿到真实用户请求,类似令牌桶,给个许可去请求下游
第三部分为回写 DB。
- 引入 Kafka 即可
中间件选用
- 当然我们可以自己实现以上的限流与熔断策略,但是有成熟的中间件给我们使用。
- Resilience4j 和 alibaba/Sentinel 都有以上的功能,最终选取了 Sentinel。
- 原因
- Sentinel 可以配置原生控制台,可视化调整。
- Sentinel 在针对 LLM 这类限流时,有 Pacing 匀速排队的功能,可以让突发的请求以均匀的速度发给下游。
- 同时 Sentinel 还有令牌桶模式,符合我们的各种流量处理需求。