使用Guava的RateLimiter完成簡單的大流量限流

FrankYou發表於2018-11-01

 限流的一般思路:

1、隨機丟棄一定規則的使用者(迅速過濾掉90%的使用者);

2、MQ削峰(比如設一個MQ可以容納的最大訊息量,達到這個量後MQ給予reject);

3、業務邏輯層使用RateLimiter進行限流;

4、最終可以承受的流量到達DB層。

package ratelimiter;

import com.google.common.util.concurrent.RateLimiter;
import org.springframework.stereotype.Component;

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

/**
 * @author xfyou
 * @date 2018/10/31
 */
@Component
public class AccessLimitService {

    private static volatile int acquireCount = 0;
    private static final Object OBJECT = new Object();

    /**
     * 每秒可以獲得50個許可證
     */
    private RateLimiter rateLimiter = RateLimiter.create(50);

    private boolean tryAcquire() {
        // 等待1秒鐘如果未能獲取到許可證就返回false,否則返回true
        return rateLimiter.tryAcquire(1, 1000, TimeUnit.MILLISECONDS);
    }

    public static void main(String[] args) {
        AccessLimitService accessLimitService = new AccessLimitService();
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 1000; i++) {
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    if (accessLimitService.tryAcquire()) {
                        System.out.println("獲取許可證,執行業務邏輯。");
                        synchronized (OBJECT) {
                            System.out.println(++acquireCount);
                        }
                        try {
                            Thread.sleep(20);
                        } catch (InterruptedException ex) {
                            //
                        }
                    } else {
                        System.err.println("未獲取到許可證,請求可以丟棄。");
                    }
                }
            });
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        executorService.shutdown();
    }
}

 

相關文章