限流-Guava
限流
- 限流场景
12306 双十一(11.11零点,由于各种商家的促销活动(前XX名免单),支付宝进入排队支付状态) 外卖业务
- 常见的限流方案
手动实现负载均衡 验证码 容器限流 限流总资源数 限流某个接口的总并发/请求数 Nginx限流 消息队列 利用Netflix的Hystrix限流
# Guava是什么
限流的概念
# Guava限流核心算法
漏桶算法 令牌桶算法 比较
# Guava限流实战
Guava RateLimiter实现平滑限流
- 平滑突发限流
import com.google.common.util.concurrent.RateLimiter;
/**
* @Description 平滑突发限流(SmoothBursty)
*/
public class SmoothBurstyRateLimitTest01 {
public static void main(String[] args) {
//每秒允许5个请求,表示桶容量为5且每秒新增5个令牌,即每隔0.2秒新增一个令牌
RateLimiter limiter = RateLimiter.create(5);
//如果当前桶中有足够令牌则成功(返回值为0)返回获取token的耗时,以秒为单位
//将突发请求速率平均为了固定请求速率,固定频率=0.2s/个
System.out.println(limiter.acquire(1));
System.out.println(limiter.acquire(1));
System.out.println(limiter.acquire(1));
System.out.println(limiter.acquire(1));
System.out.println(limiter.acquire(1));
System.out.println(limiter.acquire(1));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import com.google.common.util.concurrent.RateLimiter;
/**
* @Description 平滑突发限流(SmoothBursty) 使用场景:对冷数据的预热处理
*/
public class SmoothBurstyRateLimitTest02 {
public static void main(String[] args) {
//每秒允许5个请求,表示桶容量为5且每秒新增5个令牌,即每隔0.2秒新增一个令牌
RateLimiter limiter = RateLimiter.create(5);
//一次性消费5个令牌,模拟预热的场景(初始化redis缓存)
System.out.println(limiter.acquire(5));
//limiter.acquire(1)将等待差不多1秒桶中才能有令牌
System.out.println(limiter.acquire(1));
//固定速率
System.out.println(limiter.acquire(1));
//固定速率
System.out.println(limiter.acquire(1));
//固定速率
System.out.println(limiter.acquire(1));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import com.google.common.util.concurrent.RateLimiter;
/**
* @Description 平滑突发限流(SmoothBursty) 使用场景:对冷数据的预热处理
*/
public class SmoothBurstyRateLimitTest03 {
public static void main(String[] args) {
//每秒允许5个请求,表示桶容量为5且每秒新增5个令牌,即每隔0.2毫秒新增一个令牌
RateLimiter limiter = RateLimiter.create(5);
//第一秒突发了10个请求
System.out.println(limiter.acquire(10));
//limiter.acquire(1)将等待差不多2秒桶中才能有令牌
System.out.println(limiter.acquire(1));
//固定速率
System.out.println(limiter.acquire(1));
//固定速率
System.out.println(limiter.acquire(1));
//固定速率
System.out.println(limiter.acquire(1));
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- 平滑预热限流
import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.TimeUnit;
/**
* @Description 平滑预热限流(SmoothWarmingUp)
*/
public class SmoothWarmingUp {
public static void main(String[] args) {
//permitsPerSecond:每秒新增的令牌数 warmupPeriod:从冷启动速率过渡到平均速率的时间间隔
//系统冷启动后慢慢的趋于平均固定速率(即刚开始速率慢一些,然后慢慢趋于我们设置的固定速率)
RateLimiter limiter = RateLimiter.create(10, 1000, TimeUnit.MILLISECONDS);
for(int i = 0; i < 20;i++) {
//获取一个令牌
System.out.println(limiter.acquire(1));
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- Guava用于秒杀场景
import com.google.common.util.concurrent.RateLimiter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @Description Guava秒杀场景:Guava使得商品被均匀的被秒杀,效果较好,未秒到商品的用户引流至推荐页
*/
public class GuavaSecKill {
public static void main(String[] args) throws InterruptedException {
//限流,每秒允许10个请求进入秒杀 QPS=10 令牌生成速度=100ms/个
RateLimiter limiter = RateLimiter.create(0);
/**
* 开线程池
*/
ExecutorService executorService = Executors.newFixedThreadPool(100);
//100个线程同时抢购
for (int i = 0; i < 100; i++) {
executorService.submit(() -> {
//每个秒杀请求如果在50ms(0.05s)以内得到令牌,就算是秒杀成功,否则就返回秒杀失败
if (limiter.tryAcquire(50, TimeUnit.MILLISECONDS)) {
if (CountUtils.TOTAL_COUNT.get() > 0) {
//库存减1
CountUtils.decrease();
System.out.println("恭喜您,秒杀成功!!!");
} else {
System.out.println("秒杀失败,商品已售完");
}
} else {
System.out.println("秒杀失败,请继续努力~");
}
});
//给limiter 0.01s的时间生成新的令牌生成
Thread.sleep(10);
}
Thread.sleep(1000);
executorService.shutdown();
}
}
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
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
Guava对比其他限流方案的特点
# 备注