【限流】Token令牌桶新用法CirculateNoTokenBucket

说到限流,我们最多想到的是google公司的guava的RateLimit限流工具类。令牌桶算法用来控制发送到网络上的数据的数目,并允许突发数据的发送。其实对于限制接口流量不是特别好

<dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>23.0</version>
        </dependency>

以下是根据令牌桶算法改后的用法:如有问题,请多多批评!!!

代码地址:https://gitee.com/xiaobaer/Svimer/tree/master/svimer-core

首先确认的是,令牌桶里没有令牌,只是令牌信号量。异常令牌桶里才有令牌,令牌存放接口信息。

CirculateNoTokenBucket可以在调用接口前限制流量,还可以在调用接口后根据异常令牌监控接口使用情况。

创建一个固定容量及固定令牌信号量的容器CirculateNoTokenBucket circulateNoTokenBucket = CirculateNoTokenBucket.newBuilder().tokenBucketSize(15).build();

获取令牌桶空的信号量circulateNoTokenBucket.getTokenQueueRemainingCapacity()

获取有异常的令牌数量circulateNoTokenBucket.getAbnormalTokensSize()

输出异常令牌信息circulateNoTokenBucket.toString()

 

代码:

import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import com.svimer.core.token.CirculateNoTokenBucket;
import com.svimer.core.token.Token;

public class CirculateNoTokenBucketTest {
    public static void main(String[] args) throws InterruptedException {
        CirculateNoTokenBucket circulateNoTokenBucket = CirculateNoTokenBucket.newBuilder().tokenBucketSize(15).build();
        int size = 4;
        ExecutorService pool = Executors.newFixedThreadPool(size);
        while (true) {
            TimeUnit.MILLISECONDS.sleep(500);
            pool.execute(new Task(circulateNoTokenBucket));

        }

    }

    static class Task implements Runnable {

        private CirculateNoTokenBucket circulateNoTokenBucket;

        public Task(CirculateNoTokenBucket circulateNoTokenBucket) {
            this.circulateNoTokenBucket = circulateNoTokenBucket;
        }

        @Override
        public void run() {
            boolean tokens = circulateNoTokenBucket.getTokens(1);
            if (tokens) {
                try {
                    long startTime = System.currentTimeMillis(); // 获取出来的是当前时间的毫秒值
                    // 业务处理耗时
                    Random r = new Random();
                    TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                    long endTime = System.currentTimeMillis(); // 获取出来的是当前时间的毫秒值
                    // 毫秒
                    long threshold = 500l;
                    long timeDifference = endTime - startTime;
                    if (timeDifference > threshold) {
                        Token token = new Token();
                        token.setEndTime(endTime);
                        token.setStartTime(startTime);
                        token.setTimeDifference(timeDifference);
                        token.setToken("abc");
                        token.setUrl("action地址");
                        circulateNoTokenBucket.addAbnormalToken(token);
                        System.out.println(circulateNoTokenBucket.getTokenQueueRemainingCapacity());
                        System.out.println(circulateNoTokenBucket.getAbnormalTokensSize());
                        
                        System.out.println(circulateNoTokenBucket.toString());
                    } else {
                        circulateNoTokenBucket.addTokens(1);
                    }
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            } else {
                System.out.println("token rejuect=========Execute ThreadName=" + Thread.currentThread().getName());
            }

        }

    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章