1. 程式人生 > >使用Guava的RateLimiter完成簡單的大流量限流

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

 限流的一般思路:

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(); } }