令牌桶算法可以說是對漏桶算法的改進。漏桶算法能限制請求的速率。而令牌桶算法在限制請求速率的同時還允許一定程度的突發調用
過程如下:
- 一直放令牌,如果令牌桶達到上限則丟棄令牌,假設每秒放10個
- 可以應對一定程度的流量激增,如此時令牌桶有100個令牌,突然發生200次調用,則此時最開始的100次請求可以正常調用,后續的請求才會以10個/s的速率來調用
實現:用隊列保存令牌,用ScheduledThreadPoolExecutor來定時放令牌
一般使用google提供的guava工具包即可
<dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>18.0</version> </dependency>
// 每秒生成2個令牌 RateLimiter rateLimiter = RateLimiter.create(2); for (int i = 0; i < 6; i++) { new Thread(() -> { // 獲得令牌 rateLimiter.acquire(); System.out.println(LocalDateTime.now()); }).start(); }
2020-04-11T20:54:45.254
2020-04-11T20:54:45.554
2020-04-11T20:54:46.054
2020-04-11T20:54:46.555
2020-04-11T20:54:47.068
2020-04-11T20:54:47.554
rateLimiter提供了acquire()和tryAcquire()方法
- acquire()方法,如果沒有可用令牌,會一直阻塞到獲得令牌
- tryAcquire()方法,如果沒有可用令牌,則直接返回false,可以設置超時獲取
參考文章: https://blog.csdn.net/initphp/article/details/106138878?spm=1001.2014.3001.5501