Java 高并发限流实战:Guava RateLimiter 与 Sentinel 对比

CLARA轻量论坛系统
CLARA轻量论坛系统 星耀SVIP管理员 黑卡会员
发布于 2026-08-18 01:27 ·4 浏览 ·0 回复

照着做完,你能跑通 Guava RateLimiter 与 Sentinel 两套限流代码,并知道什么场景该用哪个、各自的坑在哪。

第一步:先分清你要的是单机限流还是集群限流

这是选型的唯一分水岭。Guava RateLimiter 是进程内的令牌桶,几个 JVM 就有几个桶——服务部署 4 个实例、每个配 100 QPS,实际入口能打进来 400 QPS。Sentinel 的规则可以走 Nacos/Apollo 下发到全部实例,也可以做集群限流。

判断方法很简单:你有一台机器就 Guava,多台机器且要卡住总入口 QPS,就 Sentinel。

第二步:跑起 Guava RateLimiter

引入依赖,只要一个包:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

最小可用代码:

// 每秒放行 100 个请求,令牌桶平滑发放
private final RateLimiter limiter = RateLimiter.create(100.0);

public void handle() {
    // 拿不到就立刻返回,不阻塞线程(推荐)
    if (!limiter.tryAcquire(1, 200, TimeUnit.MILLISECONDS)) {
        throw new RuntimeException("请求过于频繁");
    }
    // 业务逻辑
}

两个构造函数要选对:

  • `RateLimiter.create(100)` → SmoothBursty,允许突发,桶里会攒令牌;
  • `RateLimiter.create(100, 5, TimeUnit.SECONDS)` → SmoothWarmingUp,5 秒预热到 100 QPS,适合刚启动还没热缓存、连接池没建满的服务。

注意:`limiter.acquire()` 是阻塞的,高并发下大量线程卡在这里会把 Tomcat 线程池占满,限流反而变成雪崩。线上优先用带超时的 `tryAcquire`。

第三步:跑起 Sentinel

Sentinel 分三块:核心包、注解切面、控制台。

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-core</artifactId>
    <version>1.8.6</version>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-annotation-aspectj</artifactId>
    <version>1.8.6</version>
</dependency>

启动控制台(默认账号密码都是 `sentinel`):

java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 \
     -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar

业务代码加注解,并注册切面:

@Configuration
public class SentinelConfig {
    @Bean
    public SentinelResourceAspect sentinelResourceAspect() {
        return new SentinelResourceAspect();
    }
}

@SentinelResource(value = "queryOrder",
        blockHandler = "handleBlock",
        fallback = "handleFallback")
public Order queryOrder(Long id) { ... }

// 限流触发时走这里,方法签名要和原方法一致,末尾多一个 BlockException
public Order handleBlock(Long id, BlockException ex) {
    throw new RuntimeException("系统繁忙,请稍后再试");
}

然后到控制台「簇点链路」里找到 `queryOrder`,点「流控」新建规则,关键参数:阈值类型选 QPS、单机阈值填 200、流控模式选直接、流控效果选快速失败。

注意:`blockHandler` 必须和被保护方法在同一个类里,跨类调用不生效;只写了 `@SentinelResource` 但没注册 `SentinelResourceAspect`,注解等于没写。

注意:Sentinel 规则默认只存在内存里,应用一重启规则全丢。生产环境要接 Nacos 数据源持久化,否则限流形同虚设。

第四步:按场景选型

维度Guava RateLimiterSentinel
作用范围单 JVM单机 + 集群
限流模型令牌桶(平滑/预热)QPS、线程数、关联、链路
熔断降级有(慢调用、异常比例)
动态改规则改代码重启控制台实时下发
接入成本一个依赖依赖 + 控制台 + 持久化

结论:单体应用、只想给某个方法或第三方接口调用做保护,用 Guava,几行代码搞定;微服务、需要熔断降级和动态调参,用 Sentinel。

小结

  • 选型先看部署形态:单机 Guava,集群/微服务 Sentinel。
  • Guava 用 `tryAcquire` 带超时,别用阻塞的 `acquire`;冷启动服务用 SmoothWarmingUp。
  • Sentinel 三件套缺一不可:核心包、AspectJ 切面、控制台;`blockHandler` 要同签名同类。
  • Sentinel 规则务必接 Nacos 持久化,否则重启即失效。
  • 两者可以叠加:Sentinel 卡总入口,Guava 细粒度保护下游依赖。
本文转载自 Clara轻量论坛系统,原文地址:https://www.leleweb.cn/thread-547.html
转载请注明出处,版权归原作者所有。
他们都看过 1 人浏览过
CLARA轻量论坛系统

全部回复 0

还没有回复,来抢沙发~