1.什么是限流
- 针对非核心业务可以使用熔断和降级,毕竟不影响主流程服务
- 核心业务出现超出流量,使用限流,提升系统鲁棒性
- 重点掌握:限流算法
\
-
什么是限流?
-
通过限制到达系统并发请求的数量,保证系统能够与响应部分用户请求
-
超过限制的请求,会拒绝服务保证系统的可用性
-
一般部署在服务的入口层
- API网关
- RPC客户端
-
-
生活中的限流
- 旅游景区限流
- 地铁
-
TCP的滑动窗口
- 接收方根据处理能力,限制发送方的数据量
- 接收方处理速度快,窗口就大(不限流)
- 接收方处理速度慢,窗口就小(限流)
-
微服务下可以从什么方面进行流量限制
- 系统每分钟处理的请求数
- 接口每分钟处理的请求数
- 单个用户|ip每分钟发送请求的数量
- appkey的访问接口速率
2.限流算法
限流就需要限制一段时间内向系统发起总体的请求量
2.1固定窗口
暴力+直观解法:统计一分钟的请求次数,超出的请求数直接返回错误
下一分钟重置计数器
private AtomicInteger counter; //定时清零
ScheduledExecutorService timer = Executors.newSingleThreadScheduledExecutor(); timer.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
counter.set(0); } }, 0, 1, TimeUnit.SECONDS);
//是否限流
public boolena isRateLimit() { return counter.incrementAndGet() >= allowedLimit;}
//计数器加1
counter.inc()
缺点:
无法限制短时间之内的集中流量(处理突发情况不够圆滑)
假如我们需要限制每秒钟只能处理 10 次请求,如果前一秒钟产生了 10 次请求
这 10 次请求全部集中在最后的 10 毫秒中,而下一秒钟的前 10 毫秒也产生了 10 次请求
那么在这 20 毫秒中就产生了 20 次请求,超过了限流的阈值
但是因为这 20 次请求分布在两个时间窗口内,所以没有触发限流,这就造成了限流的策略并没有生效。
2.2滑动窗口
基于固定窗口的缺点,使用滑动窗口
将时间的窗口划分为多个小窗口,每个小窗口中都有单独的请求计数
虽然解决了固定窗口不能解决突发流量的限制,但是处理还是不够平滑,实际应用中一般使用漏桶算法和令牌桶算法
3.漏桶算法
在流量产生端和接收端增加一个漏桶,流量会进入和暂存到漏桶中,漏桶出口会按照固定速率输出到接收端
保证了所有流量平滑到达服务端
一般使用消息队列(对流量进行削峰填谷)
\
4.令牌桶算法
-
在一秒内限制访问次数为N次,没隔1/N的时间,往桶内放入一个令牌
-
新的请求每次获取一个令牌,如果没有令牌则看策略
- 拒绝服务
- 阻塞等待
-
通过定期放入令牌,是的避免损失流量高峰(类似消息队列的削峰填谷)
-
优化:可以预置一些令牌在其中
-
相比于漏桶算法更适合互联网环境,不需要向漏桶缓缓存请求
-
实现
- 单机:使用一个数值即可
- 分布式:使用redis,可以获取一批令牌
5.总结
-
限流是一种和常见的保护策略,可以针对不同维度进行限流
-
基于时间窗口维度有固定算法和滑动窗口算法,但是处理都不够平滑
-
令牌桶算法和漏桶算法则能够塑形流量,让流量更加平滑,但是令牌桶算法能够应对一定的突发流量,所以在实际项目中应用更多(削峰填谷)\
-
限流策略是微服务治理中的标配策略,只是你很难在实际中确认限流的阈值是多少,设置的小了容易误伤正常的请求,设置的大了则达不到限流的目的\
-
需要动态调整\
-
根据压测结果进行调整
-