上一篇 <<<服务限流之滑动窗口计数
下一篇 >>>服务限流之漏桶算法
令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。
令牌桶算法的描述如下:
假设限制2r/s,则按照500毫秒的固定速率往桶中添加令牌;
桶中最多存放b个令牌,当桶满时,新添加的令牌被丢弃或拒绝;
当一个n个字节大小的数据包到达,将从桶中删除n个令牌,接着数据包被发送到网络上;
如果桶中的令牌不足n个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>
</dependencies>
/*
* RateLimiter是guava提供的基于令牌桶算法的实现类,可以非常简单的完成限流特技,并且根据系统的实际情况来调整生成token的速率。
* 使用RateLimiter 实现令牌通方式限流
*/
@RestController
public class IndexController {
@Autowired
private OrderService orderService;
// create 方法中传入一个参数 以每秒为单位固定的速率值 1r/s 每秒中往桶中存入一个令牌
RateLimiter rateLimiter = RateLimiter.create(100); // 独立线程
// 相当于该接口每秒钟时间 只能支持一个客户端访问
@RequestMapping("/addOrder")
public String addOrder() {
// 1.限流处理 限流正常要放在网关 客户端从桶中获取对应的令牌,为什么返回double结果,这个结果表示 从桶中拿到令牌等待时间.
// 2. 如果获取不到令牌,就会一直等待.设置服务降级处理(相当于配置在规定时间内如果没有获取到令牌的话,直接走服务降级。)
// double acquire = rateLimiter.acquire();
//
// System.out.println("从桶中获取令牌等待的时间:" + acquire);
// 如果在500毫秒内如果没有获取到令牌的话,则直接走服务降级处理
boolean tryAcquire = rateLimiter.tryAcquire(500, TimeUnit.MILLISECONDS);
if (!tryAcquire) {
System.out.println("别抢了, 在抢也是一直等待的, 还是放弃吧!!!");
return "别抢了, 在抢也是一直等待的, 还是放弃吧!!!";
}
// 2. 业务逻辑处理
boolean addOrderResult = orderService.addOrder();
if (addOrderResult) {
System.out.println("恭喜您,抢购成功! 等待时间:" + rateLimiter.acquire());
return "恭喜您,抢购成功!";
}
return "抢购失败!";
}
}
推荐阅读:
<<<高并发架构的整体思路
<<<一个网站访问慢的真正原因
<<<高并发情况下,接口的代码会存在哪些问题
<<<压缩静态资源减少带宽传输的方式
<<<动静分离架构模式
<<<缓存策略汇总
<<<后端服务的雪崩效应及解决思路
<<<服务的隔离、降级和熔断
<<<服务限流之计数器方式
<<<服务限流之滑动窗口计数
<<<服务限流之漏桶算法
<<<漏桶算法和令牌桶算法的区别
<<<自定义封装限流算法
<<<应用级限流
<<<接入层限流