/** * @create 2021-02-15 11:35 * @desc 请求类 **/ public class Request { private final int data; public Request(int data) { this.data = data; } public int getData() { return data; } @Override public String toString() { return "Request{" + "data=" + data + '}'; } }
--------------------
import com.google.common.util.concurrent.Monitor; import com.google.common.util.concurrent.RateLimiter; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.Consumer; import static java.lang.Thread.currentThread; /** * @create 2021-02-15 11:36 * @desc 漏桶算法的应用 **/ public class RateLimiterBucket { //漏桶采用线程安全的容器 private final ConcurrentLinkedQueue<Request> bucket = new ConcurrentLinkedQueue<>(); //定义漏桶的上沿容量 private final static int BUCKET_CAPACITY = 10; //定义漏桶的下沿水流速率,每秒匀速放行 5 个 Request private final RateLimiter rateLimiter = RateLimiter.create(5.0D); //提交请求时需要用到的 Monitor private final Monitor requestMonitor = new Monitor(); //处理请求时需要用到的 Monitor private final Monitor handleMonitor = new Monitor(); public void submitRequest(int data) { this.submitRequest(new Request(data)); } // 该方法主要用于接受来自客户端提交的请求数据 public void submitRequest(Request request) { /** * enterIf() 方法: 主要用于判断当前的 Guard 是否满足临界值的判断, * 也是使用比较多的一个操作,调用该方法,当前线程 * 并不会进入阻塞之中 */ if(requestMonitor.enterIf(new Monitor.Guard(requestMonitor) { @Override public boolean isSatisfied() { return bucket.size() < BUCKET_CAPACITY; } })) { try { // 向桶中加入新的 request boolean result = bucket.offer(request); if(result) { System.out.println(currentThread() + " submit request : " + request.getData()+ " successfully."); } else { // 此处可以将请求数据存入“高吞吐量的 MQ 中”,然后从 MQ 中消费请求,再尝试提交 System.out.println("produce into MQ and will try again later."); } } finally { requestMonitor.leave(); } } else { // 当漏桶溢出的时候做“降权”处理 System.out.println("The request:" + request.getData() + "will be down-dimensional handle" + "due to bucket is overflow"); // 此处可以将请求数据存入“高吞吐量的 MQ 中”,然后从 MQ 中消费请求,再尝试提交 System.out.println("produce into MQ and will try again later."); } } // 该方法主要从漏桶中匀速地处理相关请求 public void handleRequest(Consumer<Request> consumer) { // 若漏桶中存在请求,则处理 if( handleMonitor.enterIf(new Monitor.Guard(handleMonitor) { @Override public boolean isSatisfied() { return !bucket.isEmpty(); } })) { try { // 匀速处理 rateLimiter.acquire(); // 处理数据 consumer.accept(bucket.poll()); } finally { handleMonitor.leave(); } } } }
-----------------------
import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; /** * @create 2021-02-15 15:15 * @desc 测试自定义的 RateLimiterBucket **/ public class Test { private static final AtomicInteger data = new AtomicInteger(0); private static final RateLimiterBucket bucket = new RateLimiterBucket(); public static void main(String[] args) { //启动 10 个线程模拟高并发的业务请求 for(int i = 0 ; i < 20 ; i++) { new Thread( ()-> { while(true) { bucket.submitRequest(data.getAndIncrement()); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } } } ).start(); } //启动 10 个线程模拟匀速地对漏桶中的请求进行处理 for(int i = 0 ; i < 10 ; i++) { new Thread( ()-> { while(true) { bucket.handleRequest(System.out::println); } } ).start(); } } }