限流的一般思路:
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(); } }