前言
之前也用到过 这个漏桶算法实现的限流 但是不是我写的 也没怎么关注
这次看到redis书中提到了 就顺便写一篇笔记记录一下 方便后续查询
算法原理
参考文档: https://baike.baidu.com/item/%E6%BC%8F%E6%A1%B6%E7%AE%97%E6%B3%95/8455361
总的来说 就是类似小学应用题中的 游泳池 边放水 边进水 当游泳池满了之后 不能再进水
漏桶算法 适合整理流量
但是对于突发特性的流量来说 适应性不是很强
很容易导致游泳池满了导致拒绝访问
懒的截图 手画个简略图 意思意思
1 2 3 4 5 6 7 8 9 10 11 12 13
| ------ ·输入流量 · ---------------- \ / ·溢出流量 \ 桶 / · \ / ------- · ·输出流量 ·
|
实例
java编写
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| package com.ming;
import lombok.extern.slf4j.Slf4j; import org.junit.Test;
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue;
@Slf4j public class LeakyBucketTest {
@Test public void test() throws InterruptedException { int maxSize = 10; int inputSleepTime = 1; int outputSleepTime = 2; mockLeakyBucket(maxSize, inputSleepTime, outputSleepTime); Thread.sleep(100000000L); }
private void mockLeakyBucket(int maxSize, int inputSleepTime, int outputSleepTime) { Queue<String> bucket = new ArrayBlockingQueue<>(maxSize);
new Thread(() -> { while (true) { try { Thread.sleep(inputSleepTime * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } try { bucket.add("流量:" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } catch (Exception e) { e.printStackTrace(); log.error("流量溢出" + bucket.size() + ";" + Thread.currentThread().getName()); } } }).start();
new Thread(() -> { while (true) { try { Thread.sleep(outputSleepTime * 1000L); } catch (InterruptedException e) { e.printStackTrace(); } log.info("输出流量:" + bucket.poll() + ";" + Thread.currentThread().getName()); } }).start(); } }
|
总结
漏桶算法 原理还是很简单的 就是一个输入输出速率和中间桶的处理
漏桶算法适合流量较为稳定的情况 用来整理流量 处理少量突发流量
如果有突发流量 只能就要取调整桶大小或者输出流量速率来达到适应突发流量
如果加桶大小 延迟就会高
不过企业项目中 很少会有大量突发流量 所以用漏桶算法一般也足够了