一、为什么要实现服务限流
秒杀抢购、双11、服务安全(流量攻击、DDOS)、雪崩效应 因为流量突然特别大。
二、限流方式
1、计数器方式
比如某个接口1分钟的请求不能超过10次,那么就可以设置一个计数器,每次请求,计数器加1。先判断上一次执行时间与当前时间是否在1分钟之内,若在1分钟之类则将次数累加一然后return 当前次数<=10。若大于1分钟则重置计数器 return true。传统模式的弊端,在临界值时若出现大量的请求,就不符合每分钟10次的要求。
private int limtCount = 10;// 限制最大访问的容量
AtomicInteger atomicInteger = new AtomicInteger(0); // 每秒钟 实际请求的数量
private long start = System.currentTimeMillis();// 获取当前系统时间
private int interval = 60;// 间隔时间60秒
public boolean acquire() {
long newTime = System.currentTimeMillis();
if (newTime > (start + interval)) {
// 判断是否是一个周期
start = newTime;
atomicInteger.set(0); // 清理为0
return true;
}
atomicInteger.incrementAndGet();// i++;
return atomicInteger.get() <= limtCount;
}
2、滑动窗口计数
算法原理:在一分钟之类分为6个格子,每个格子都有自己独立的计数器。当所有格式都满了后,会重新创建一个格子,重新开始计数。可以解决传统计数器的临界值问题。
3、令牌桶算法
算法原理:开启个独立线程以固定速率往桶里添加令牌,在访问接口的时候先从桶里获取令牌,若获取不到令牌,直接拒绝访问服务。
a、使用 RateLimiter实现令牌桶限流:
//导包
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guav