Java:限流器(RateLimiter)原理与实现

限流器(RateLimiter)主要有两种算法:

  • 漏桶算法
  • 令牌桶算法

它们都是网络世界中流量整形(Traffic Shaping)或速率限制(Rate Limiting)时经常使用的算法。

漏桶算法

漏桶算法(Leaky Bucket),它的主要目的是控制数据注入到网络的速率,平滑网络上的突发流量。漏桶算法提供了一种机制,通过它,突发流量可以被整形以便为网络提供一个稳定的流量。

漏桶可以看作是一个带有常量服务时间的单服务器队列,如果漏桶(包缓存)溢出,那么数据包会被丢弃。 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量。

如图所示,把请求比作是水,水来了都先放进桶里,并以限定的速度出水,当水来得过猛而出水不够快时就会导致水直接溢出,即拒绝服务。

Java:限流器(RateLimiter)原理与实现_第1张图片

令牌桶算法

令牌桶算法(Token Bucket),用来控制发送到网络上的数据的数目,并允许突发数据的发送。

令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务。从原理上看,令牌桶算法和漏桶算法是相反的,一个“进水”,一个是“漏水”。

Java:限流器(RateLimiter)原理与实现_第2张图片

漏桶算法&令牌桶算法的区别

漏桶算法与令牌桶算法的区别在于,漏桶算法能够强行限制数据的传输速率,令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输。

需要注意的是,在某些情况下,漏桶算法不能够有效地使用网络资源,因为漏桶的漏出速率是固定的,所以即使网络中没有发生拥塞,漏桶算法也不能使某一个单独的数据流达到端口速率。因此,漏桶算法对于存在突发特性的流量来说缺乏效率。而令牌桶算法则能够满足这些具有突发特性的流量。通常,漏桶算法与令牌桶算法结合起来为网络流量提供更高效的控制。

下面介绍Java中一些实现了令牌桶算法的常用组件。

单机限流

1、resilience4j-ratelimiter

https://resilience4j.readme.io/docs/ratelimiter


    io.github.resilience4j
    resilience4j-ratelimiter
    1.3.1

RateLimiterConfig config = RateLimiterConfig.custom()
  .limitRefreshPeriod(Duration.ofMillis(1))
  .limitForPeriod(10)
  .timeoutDuration(Duration.ofMillis(25))
  .build();

// Create registry
RateLimiterRegistry rateLimiterRegistry = RateLimiterRegistry.of(config);

// Use registry
RateLimiter rateLimiterWithDefaultConfig = rateLimiterRegistry
  .rateLimiter("name1");

RateLimiter rateLimiterWithCustomConfig = rateLimiterRegistry
  .rateLimiter("name2", config)

2、Guava: Google Core Libraries for Java

https://github.com/google/guava


  com.google.guava
  guava
  28.2-jre
 
  28.2-android

RateLimiter limiter = RateLimiter.create(1);//限制qps最大为1
System.out.println(limiter.acquire()); //输出阻塞的时间

 

分布式限流

1、Redisson - Redis Java client

https://github.com/redisson/redisson


   org.redisson
   redisson
   3.12.1

Config config = Config.fromYAML(new File("config-file.yaml"));
RedissonClient redisson = Redisson.create(config);
RRateLimiter rateLimiter = redisson.getRateLimiter("myRateLimiter");

 2、alibaba - Sentinel

https://github.com/alibaba/Sentinel

https://github.com/alibaba/Sentinel/wiki/介绍


    com.alibaba.csp
    sentinel-core
    1.8.1

private static void initFlowRules(){
    List rules = new ArrayList<>();
    FlowRule rule = new FlowRule();
    rule.setResource("HelloWorld");
    rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
    // Set limit QPS to 20.
    rule.setCount(20);
    rules.add(rule);
    FlowRuleManager.loadRules(rules);
}
public static void main(String[] args) {
    // 配置规则.
    initFlowRules();

    while (true) {
        // 1.5.0 版本开始可以直接利用 try-with-resources 特性
        try (Entry entry = SphU.entry("HelloWorld")) {
            // 被保护的逻辑
            System.out.println("hello world");
	} catch (BlockException ex) {
            // 处理被流控的逻辑
	    System.out.println("blocked!");
	}
    }
}

参考文档

接口限流算法:漏桶算法和令牌桶算法
https://my.oschina.net/u/4129361/blog/3053350

漏桶算法&令牌桶算法理解及常用的算法
https://www.jianshu.com/p/c02899c30bbd

 

你可能感兴趣的:(Java,RateLimiter,限流)