1526 字
约 5 分钟
0
Guava 限流入门

Guava 限流入门

1. 一句话简介

Guava 是 Google 开源的 Java 工具库,其中 RateLimiter(令牌桶默认实现 SmoothBurty)用于对代码段的执行速率做平滑限制,即「限流」。核心思路是:以固定速率向令牌桶中放令牌,请求执行前必须先拿到一个令牌,令牌耗尽时请求被拒绝,从而把瞬时流量摊平、保护下游服务不被冲垮。

在 Spring Boot 中(参照本 demo),通常把它与 AOP 结合做成「声明式限流」:自定义一个 @RateLimiter 注解标记在接口方法上,再由切面 RateLimiterAspect 拦截被标注的方法,调用 RateLimiter.tryAcquire(timeout, timeUnit) 尝试取令牌——拿到则放行执行 point.proceed(),拿不到则抛出异常交给全局异常处理器返回友好的提示。业务代码只加一个注解即可获得限流能力,与限流逻辑完全解耦。

2. 什么时候使用

  • 单机部署、单实例限流:Guava RateLimiter 状态只存在当前 JVM 进程内,天然适合单体或单实例应用,无需任何外部依赖。
  • 对接口做 QPS 上限保护:需要精确控制「每秒最多允许 N 次请求」,如本 demo 中 @RateLimiter(value = 1.0) 表示每秒最多放行 1 次。
  • 想用最少代码接入、快速落地:只需引一个 guava 依赖 + 一个切面类,配上注解即可,无需引入 Redis、MQ 等外部组件。
  • 需要平滑限流而非直接拦截:令牌桶算法允许一定程度的突发、频率放行平滑,比冷硬的「滑动窗口一刀切拒绝」体验更好。
  • 只对部分接口限流:基于 @annotation 切入点精准拦截,没加注解的接口完全不受影响(对应 demo 中 test2 对照接口),侵入面小。
  • 分布式/多实例集群限流RateLimiter 状态不能跨进程共享,每个实例各自计数,集群下无法做到全局阈值一致。需改用 Redis + Lua 或 Sentinel 等分布式方案。
  • 接口级精确的流量整形与复杂场景RateLimiter 只控制速率,不做请求去重、内存级熔断降级、动态规则下发等高级治理。
  • 需要限流规则动态可配置/可热更新:Guava 限流器参数需在代码里写死或用 setRate() 手动调整,缺乏管理端支持。
  • 单点进程内状态,重启即清零:进程重启后限流器重新创建,无法持久化历史流量与配额。

3. 常见业务场景

  • 接口防刷、防恶意频繁访问:对公开 API(如查询/登录接口)加上限流,防止被脚本高频轮询打爆。贴合本 demo 的 test1(QPS=1)演示——快速刷新时返回「手速太快了,慢点儿吧〜」而不是去执行业务。
  • 保护下游关键资源(DB / 第三方接口 / 令牌):当业务逻辑会调用外部受配额限制的服务(短信、支付、OpenAI 等)时,先用 RateLimiter 收敛本地调用速率,避免超额。demo 中通过 RATE_LIMITER_CACHEConcurrentHashMap)按方法缓存限流器,保证每个接口独立、稳定地限速。
  • 突发流量平滑 / 削峰:秒杀、抢单等高并发瞬间涌入时,用令牌桶把尖峰流量摊平到一段时间内处理,避免服务瞬时过载。tryAcquire(timeout, timeUnit) 支持短暂排队等待,比硬拒绝更柔和。
  • 功能开关式的按接口差异化限流:通过 @RateLimitervalue/qps 参数,不同接口配置不同阈值(demo 中 test3 的 QPS=2 就是 test1 的两倍),实现同一套切面下的差异化治理。
  • 为手动/定时任务做自我保护:对某些需要读库、拉外部数据但又不要求实时的后台任务,用限流控制执行节奏,避免一次性拉取过大。

4. 同类技术对比

维度 Guava RateLimiter(本 demo) Redis + Lua(滑动窗口/令牌桶) Alibaba Sentinel JDK Semaphore
算法/能力 令牌桶,控制速率 可自实现固定窗口/滑动窗口,控制速率与窗口计数 限流+熔断+降级(并发数、QPS、链路) 信号量,只控制并发数
分布式能力 仅单机 强,跨实例全局统一 支持集群,配合控制台 仅单机
外部依赖 无(纯 JVM 库) 需 Redis 需引入客户端/控制台(较重) 无(JDK 内置)
易用性/接入成本 极低,注解+AOP 即插即用 中,需写 Lua 脚本并维护分布式一致性 较高,依赖重、学习曲线陡 低,写少量同步代码
动态规则/治理 弱,参数写死,进程内状态 可通过脚本/配置下发 强,控制台可视化配置与实时监控
适用规模 单实例、中小场景、快速落地 分布式/多实例、需要全局阈值 大规模微服务、复杂治理需求 单纯控制并发上限

选型建议:单机应用、想用最少成本快速给接口加 QPS 上限,选 Guava RateLimiter 足够(也是本模块演示的方案);一旦应用横向扩展成多实例集群、需要全局统一的限流阈值,应切换到 Redis + Lua 或改为自实现分布式令牌桶;若面对的是大型微服务、还要熔断降级、动态规则和可视化治理,直接上 Sentinel;而如果目标只是「限制同时进行的并发数」(而非速率),用 JDK 自带 Semaphore 即可,无需任何三方依赖。

Guava 限流入门
http://www.clxhxhhr.top/posts/487/
作者
clxstart
发布于
2026-09-07
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。