Java implements current limiting algorithm

The current limiting algorithm refers to a method of controlling traffic in a distributed system. It is used to prevent the system from being congested with too many requests, causing performance degradation or crashes.

Common current limiting algorithms include the following:

  1. Fixed Window Algorithm: Divide time into fixed time windows, and only allow a certain number of requests in each time window.

  2. Sliding Window Algorithm: Divide time into fixed-size time periods. Only a certain number of requests are allowed in each time period, and as time goes by, old time periods will be deleted.

  3. Leaky Bucket Algorithm: Treat requests as water drops, and the leaky bucket acts as a buffer to limit the rate at which traffic passes.

  4. Token Bucket Algorithm: Treat requests as tokens. The system generates tokens at a certain rate and puts them into the token bucket. Each request needs to obtain a token from the token bucket. Only when the token is obtained The card request can be approved.

  5. Only N requests can be accepted per second algorithm (Guava RateLimiter): Using the token bucket algorithm, a fixed number of tokens are generated per second, and each request needs to obtain a token to pass.

Choosing an appropriate current limiting algorithm requires comprehensive consideration based on actual scenarios and system load conditions to ensure system availability and performance.

In Java, we can use the token bucket algorithm to implement current limiting. The following is a simple current limiting implementation based on the token bucket algorithm:

import java.util.concurrent.TimeUnit;

public class RateLimiter {

    private final int capacity;        // 令牌桶容量
    private final int tokensPerSecond; // 每秒新增的令牌数
    private int tokens;                // 当前令牌数量
    private long timestamp;            // 上一次获取令牌的时间

    public RateLimiter(int capacity, int tokensPerSecond) {
        this.capacity = capacity;
        this.tokensPerSecond = tokensPerSecond;
        this.tokens = capacity;
        this.timestamp = System.currentTimeMillis();
    }

    public synchronized boolean tryAcquire(int numTokens) {
        // 计算经过的时间
        long currentTime = System.currentTimeMillis();
        long elapsedTime = currentTime - timestamp;
        // 根据时间和令牌生成速率,新增令牌数
        int newTokens = (int) (elapsedTime / 1000 * tokensPerSecond);
        tokens = Math.min(tokens + newTokens, capacity);
        timestamp = currentTime;
        // 判断令牌是否足够
        if (numTokens <= tokens) {
            tokens -= numTokens;
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        RateLimiter rateLimiter = new RateLimiter(10, 2); // 每秒新增2个令牌
        for (int i = 0; i < 20; i++) {
            if (rateLimiter.tryAcquire(1)) {
                System.out.println("执行业务逻辑");
            } else {
                System.out.println("限流");
            }
            // 暂停一段时间,模拟请求的时间间隔
            try {
                TimeUnit.MILLISECONDS.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

In the above example, we use tryAcquirethe method to try to obtain a specified number of tokens. The return value trueindicates that the token acquisition is successful and business logic can be executed. The return value falseindicates that the token acquisition fails and current limiting processing is required.

You can configure the token bucket capacity and generation rate according to your needs, adjustments capacity, and parameters. tokensPerSecondAt the same time, you can also implement more complex current limiting strategies based on specific business scenarios.

Guess you like

Origin blog.csdn.net/m0_37649480/article/details/135334727