參考教程:2小時吃透4種分布式限流算法
1.計數器限流
public class CounterLimiter {// 開始時間private static long startTime = System.currentTimeMillis();// 時間間隔,單位為msprivate long interval = 1000L;// 限制訪問次數private int limitCount = 2;// 訪問次數private int reqCount = 0;private synchronized boolean tryAcquire(){long nowTime = System.currentTimeMillis();if(nowTime < startTime + interval){if(reqCount + 1 > limitCount){System.out.println(Thread.currentThread().getName() + "被限流了");return true;}reqCount++;System.out.println(Thread.currentThread().getName() + "通過了");return false;}else {reqCount = 1;startTime = nowTime;System.out.println(Thread.currentThread().getName() + "通過了");return false;}}public static void main(String[] args) {CounterLimiter counterLimiter = new CounterLimiter();for (int i = 0; i < 10; i++) {new Thread(() ->{counterLimiter.tryAcquire();}).start();}}}
2.滑動時間窗口限流
import java.util.LinkedList;public class SlidingTimeWindowLimiter {// 請求數量private int reqCount;// 窗口集合private LinkedList<Integer> slots = new LinkedList<>();// 限制訪問量private int limitNum = 2;// 窗口數量private int windowNum = 100;// 每個窗口的時間范圍,單位msprivate long windowLength = 100L;public synchronized Boolean limit(){if(reqCount + 1 > limitNum){System.out.println(Thread.currentThread().getName() + ": 被攔截了");return true;}reqCount++;slots.set(slots.size() - 1, slots.peekLast() + 1);System.out.println(Thread.currentThread().getName() + ": 通過了");return false;}public SlidingTimeWindowLimiter(){slots.addLast(0);new Thread(() -> {while (true){try {Thread.sleep(windowLength);}catch (InterruptedException e){e.printStackTrace();}slots.addLast(0);if(slots.size() > windowNum){reqCount = reqCount - slots.peekLast();slots.removeLast();System.out.println("滑動格子:" + reqCount);}}}).start();}public static void main(String[] args) {SlidingTimeWindowLimiter slidingTimeWindowLimiter = new SlidingTimeWindowLimiter();for (int i = 0; i < 10; i++) {new Thread(() -> {slidingTimeWindowLimiter.limit();}).start();}}}
3.漏桶算法
public class LeakyBucketLimiter {// 初始時間private long timestamp = System.currentTimeMillis();// 漏桶容量private long capacity = 5;// 流出速率private long rate = 10;// 桶內有多少請求private long water = 0;public synchronized Boolean limit(){long now = System.currentTimeMillis();water = Math.max(0, water - (now - timestamp) / 1000 * rate);timestamp = now;if((water + 1) <= capacity){water++;System.out.println(Thread.currentThread().getName() + "通過了");return false;}else{System.out.println(Thread.currentThread().getName() + "被攔截了");return true;}}public static void main(String[] args) {LeakyBucketLimiter counterLimiter = new LeakyBucketLimiter();for (int i = 0; i < 10; i++) {new Thread(() ->{counterLimiter.limit();}).start();}}}
4.令牌桶算法
public class TokenBucketLimiter {// 初始時間private long timeStamp = System.currentTimeMillis();// 令牌桶容量private long capacity = 5;// 每秒生成令牌的數量private long rate = 2;// 桶內的令牌數private long tokens = 0;public synchronized Boolean limit(){long now = System.currentTimeMillis();tokens = Math.min(capacity, tokens + (now - timeStamp) * rate);timeStamp = now;// 沒有令牌了if(tokens < 1){System.out.println(Thread.currentThread().getName() + "被攔截了");return true;}else {tokens--;System.out.println(Thread.currentThread().getName() + "通過了");return false;}}public static void main(String[] args) {TokenBucketLimiter slidingTimeWindowLimiter = new TokenBucketLimiter();for (int i = 0; i < 10; i++) {new Thread(() -> {slidingTimeWindowLimiter.limit();}).start();}}
}