架构师

您现在的位置是:首页 > 技术博客 > 编程基础

编程基础

6种限流方法之服务端令牌算法(结合guava工具包)

架构师小跟班 2020-05-19 编程基础
令牌算法在令牌桶算法中有一个程序以某种恒定的速度生成令牌,并存入令牌桶中。每个请求必须先获取令牌才能执行,请求如果没有获取到令牌,可以选择等待,也可以放弃执行,如下图所示

令牌算法

在令牌桶算法中有一个程序以某种恒定的速度生成令牌,并存入令牌桶中。每个请求必须先获取令牌才能执行,请求如果没有获取到令牌,可以选择等待,也可以放弃执行,如下图所示:

我们可以使用 Google 开源的 guava 包,很方便的实现令牌桶算法,首先在 pom.xml 添加 guava 引用,配置如下:

<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>28.2-jre</version>
</dependency>

具体实现代码如下:

package com.example.demo;

import com.google.common.util.concurrent.RateLimiter;

import java.time.Instant;

/**
 * 6种限流方法之服务端令牌算法
 *
 * @author www.jiagou1216.com
 */
public class RateLimiterDemo {
    public static void main(String[] args) {
        // 每秒产生 10 个令牌(每 100 ms 产生一个)
        RateLimiter rt = RateLimiter.create(10);
        for (int i = 0; i < 11; i++) {
            new Thread(() -> {
                // 获取 1 个令牌
                rt.acquire();
                System.out.println("正常执行方法,ts:" + Instant.now());
            }).start();
        }
    }
}

以上程序的执行结果为:

可以看到,令牌确实是每 100ms 产生一个,而 acquire() 方法为阻塞等待获取令牌,它可以接收一个 int 类型的参数,用于指定获取令牌的个数。替代方法还有 tryAcquire(),此方法在没有可用令牌时就会返回 false 这样就不会阻塞等待了。tryAcquire() 方法也可以设置超时时间,未超过最大等待时间会阻塞等待获取令牌,如果超过了最大等待时间仍然没有可用的令牌就会返回 false。

注意:

使用 google guava 实现的令牌算法属于程序级别的单机版限流方案,而上面使用 Redis-Cell 的是分布式的限流方案。

相关阅读:

6种常见的限流方案

https://www.jiagou1216.com/blog/plan/842.html

6种限流方法之服务端时间窗口算法(结合redis):

https://www.jiagou1216.com/blog/plan/843.html

6种限流方法之服务端漏桶算法:

https://www.jiagou1216.com/blog/plan/844.html

6种限流方法之服务端令牌算法(结合guava工具包):

https://www.jiagou1216.com/blog/plan/845.html


文章评论