Java implements token bucket current limiting algorithm native minimalist implementation including stand-alone and multi-threaded versions

Introduction to Token Bucket Algorithm

The token bucket refers to a current-limiting container. The container has a maximum capacity, and a token is generated every second or every 100ms (depending on the number of requests processed by the machine per second). When the number of tokens in the capacity reaches the maximum capacity, the token The number will not change. Only when there is a request, the number of tokens is reduced (only the request to obtain the token will execute the business logic), and the token will be continuously generated, so the token bucket algorithm is a kind of elasticity current limiting algorithm

What can we do in the next step after the current limit is over? After the current limit is over, all requests are to obtain tokens, which we want to execute, but if there are still many requests, then we need a way to decide how to execute these requests , this method is called scheduling, you can read my article Scheduling Algorithm

Token Bucket Algorithm Current Limit Range:

Assuming that the maximum capacity of the token bucket is n, r tokens are generated per second

  1. Average rate: As time goes by, the average rate of processing requests is getting closer to processing r requests per second, indicating that the token bucket algorithm can control the average rate
  2. Instantaneous rate: If there are many requests coming in at an instant and it is too late to generate tokens, only n requests at most can obtain tokens to execute business logic at an instant, so the token bucket algorithm can also control the instant rate

Let me mention the leaky bucket here. Due to the fixed water output, the leaky bucket cannot cope with sudden bursts of traffic access, that is, it does not have the function of guaranteeing the instantaneous rate, but it can guarantee the average rate.

Stand-alone implementation

  1. capacity is the number of tokens in the current token bucket, and timeStamp is the time of the last request to obtain tokens. We don't really need to realize how many tokens the timer generates per second and put them into the container, just remember the time when the last request came time, and the difference between this request and the number of tokens generated during this period
  2. The following assumes that 1 token is generated in 100ms, and the maximum capacity of the token bucket is 10
  3. Thread.sleep is to simulate the interval between the arrival of different requests. You can see different phenomena by changing the interval.
public class LeakyBucketAlgorithm {
    
    
    private int capacity = 10;
    private long timeStamp = System.currentTimeMillis();

    public boolean getToken() {
    
    
        if (capacity > 0) {
    
    
            capacity--;
            return true;
        }
        long current = System.currentTimeMillis();
        if (current - timeStamp >= 100) {
    
    
            if ((current - timeStamp) / 100 >= 2) {
    
    
            	// 假设100ms产生一个令牌
                capacity += (int)((current - timeStamp) / 100) - 1;
            }
            timeStamp = current;
            if (capacity > 10) capacity = 10;
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        LeakyBucketAlgorithm leakyBucketAlgorithm = new LeakyBucketAlgorithm();
        while (true) {
    
    
//            Thread.sleep(10);
            Thread.sleep(100);
            if (leakyBucketAlgorithm.getToken()) {
    
    
                System.out.println("获取令牌成功,可以执行业务逻辑了");
            } else {
    
    
                System.out.println("获取令牌失败,请稍后重试");
            }
        }
    }
}

Multi-threaded version implementation

  1. The multi-thread implementation is also very simple, just add a synchronization lock to the method to ensure that only one request can try to obtain the token at the same time.
  2. Thread.sleep(1000) is because there are 10 threads grabbing tokens, and only one token is generated every 100ms, so grab it every 1 second, you can change this value to see the phenomenon
public class LeakyBucketAlgoritmThread {
    
    
    private int capacity = 10;
    private long timeStamp = System.currentTimeMillis();


    public synchronized boolean getToken() {
    
    
        if (capacity > 0) {
    
    
            capacity--;
            return true;
        }
        long current = System.currentTimeMillis();
        if (current - timeStamp >= 100) {
    
    
            if ((current - timeStamp) / 100 >= 2) {
    
    
                capacity += (int)((current - timeStamp) / 100) - 1;
            }
            timeStamp = current;
            if (capacity > 10) capacity = 10;
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws InterruptedException {
    
    
        LeakyBucketAlgoritmThread leakyBucketAlgorithmThread = new LeakyBucketAlgoritmThread();
        for (int i = 0; i < 10; i++) {
    
    
            new Thread(new Runnable() {
    
    
                @Override
                public void run() {
    
    
                    while (true) {
    
    
                        try {
    
    
//                            Thread.sleep(900);
                            Thread.sleep(1000);
                            if (leakyBucketAlgorithmThread.getToken()) {
    
    
                                System.out.println(Thread.currentThread().getName()+" 获取令牌成功,可以执行业务逻辑了");
                            } else {
    
    
                                System.out.println(Thread.currentThread().getName()+" 获取令牌失败,请稍后重试");
                            }
                        } catch (Exception e) {
    
    
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_45754452/article/details/120931773