RateLimiter接口限流

来源:互联网 发布:付磊 武汉大学 知乎 编辑:程序博客网 时间:2024/05/29 17:19

在开发对外接口时,为了保证系统的安全性和可靠性,往往需要限制接口的调用频率,即1s允许调用的次数,使用guava的ratelimiter比较合适。对于限流一般的算法采用是:楼桶算法和令牌桶算法。

     1、漏桶算法

         漏桶(Leaky Bucket)算法思路很简单,水(请求)先进入到漏桶里,漏桶以一定的速度出水(接口有响应速率),当水流入速度过大会直接溢出(访问频率超过接口响应速率),然后就拒绝请求,可以看出漏桶算法能强行限制数据的传输速率.示意图如下:

   

         可见这里有两个变量,一个是桶的大小,支持流量突发增多时可以存多少的水(burst),另一个是水桶漏洞的大小(rate)。

         因为漏桶的漏出速率是固定的参数,所以,即使网络中不存在资源冲突(没有发生拥塞),漏桶算法也不能使流突发(burst)到端口速率.因此,漏桶算法对于存在突发特性的流量来说缺乏效率.

     2、令牌桶算法

         令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.

 

  令牌桶的另外一个好处是可以方便的改变速度. 一旦需要提高速率,则按需提高放入桶中的令牌的速率. 一般会定时(比如100毫秒)往桶中增加一定数量的令牌, 有些变种算法则实时的计算应该增加的令牌的数量.

guave的ratelimiter采用的是令牌通的算法,假设1S需要限流5次;也就是1S会往桶里面方5个Token;如果在这1S内桶满了则不再加请求,如果空了则表示达到限制的上线了,会阻塞,知道有数据加入再次处理。

public class RateLimitTest {    public static void main(String[] args) throws ExecutionException, InterruptedException {        testRateLimiter();    }    /**     * RateLimiter类似于JDK的信号量Semphore,他用来限制对资源并发访问的线程数     */    public static void testRateLimiter() {        ListeningExecutorService executorService = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));        RateLimiter limiter = RateLimiter.create(3.0); // 每秒不超过3个任务被提交        for (int i = 0; i < 10; i++) {            limiter.acquire(); // 请求RateLimiter, 超过permits会被阻塞            final ListenableFuture<Integer> listenableFuture = executorService.submit(new Task("is " + i + "--" + limiter.getRate()));        }    }}class Task implements Callable<Integer> {    String str;    public Task(String str) {        this.str = str;    }    @Override    public Integer call() throws Exception {        System.out.println(System.currentTimeMillis() / 1000 + "---" + Thread.currentThread().getName() + "-call execute.." + str);        TimeUnit.SECONDS.sleep(10);        return 7;    }}

结果:

1493361377---pool-1-thread-1-call execute..is 0--3.0
1493361377---pool-1-thread-2-call execute..is 1--3.0

1493361378---pool-1-thread-3-call execute..is 2--3.0
1493361378---pool-1-thread-4-call execute..is 3--3.0
1493361378---pool-1-thread-5-call execute..is 4--3.0

1493361379---pool-1-thread-6-call execute..is 5--3.0
1493361379---pool-1-thread-7-call execute..is 6--3.0
1493361379---pool-1-thread-8-call execute..is 7--3.0

1493361380---pool-1-thread-9-call execute..is 8--3.0
1493361380---pool-1-thread-10-call execute..is 9--3.0

0 0
原创粉丝点击