【限流】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());
            }

        }

    }

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