【了解】熔断限流
熔断限流降级
熔断、限流、降级都是保持系统稳定运行的策略,但针对的场景有所不同。
熔断
服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个系统出现雪崩,暂时停止对该服务的调用。
上面的解释中有两个很关键的词,一个是暂时,一个是停止。
停止是说,当前服务一旦对下游服务进行熔断,当请求到达时,当前服务不再对下游服务进行调用,而是使用设定好的策略 (如构建默认值)直接返回。
暂时是说,熔断后,并不会一直不再调用下游服务,而是以一定的策略 (如每分钟调用 10 次,若均返回成功,则增大调用量)试探调用下游服务,当下游服务恢复可用时, 自动停止熔断 。
如上图,当 ServiceD 不可用时,ServiceB 应对 ServiceD 进行熔断。
限流
限流是指上游服务对本服务请求 QPS 超过阙值时,通过一定的策略(如延迟处理、拒绝处理)对上游服务的请求量进行限制,以保证本服务不被压垮,从而持续提供稳定服务。常见的限流算法有滑动窗口、令牌桶、漏桶等。
如上图,当 ServiceB 对 ServiceD 请求过多时,ServiceD 可以放弃一部分请求,保证自身服务的稳定。
限流指标
TPS
系统吞吐量是衡量系统性能的关键指标,按照事务的完成数量来限流是最合理的。
但是对实操性来说,按照事务来限流并不现实。在分布式系统中完成一笔事务需要多个系统的配合。比如我们在电商系统购物,需要订单、库存、账户、支付等多个服务配合完成,有的服务需要异步返回,这样完成一笔事务花费的时间可能会很长。如果按照TPS来进行限流,时间粒度可能会很大大,很难准确评估系统的响应性能。
HPS
每秒请求数,指每秒钟服务端收到客户端的请求数量。
如果一个请求完成一笔事务,那TPS和HPS是等同的。但在分布式场景下,完成一笔事务可能需要多次请求,所以TPS和HPS指标不能等同看待。
QPS
服务端每秒能够响应的客户端查询请求数量。
如果后台只有一台服务器,那HPS和QPS是等同的。但是在分布式场景下,每个请求需要多个服务器配合完成响应。
目前主流的限流方法多采用HPS作为限流指标。
限流方法
流量计数器
这是最简单直接的方法,比如限制每秒请求数量100,超过100的请求就拒绝掉。
但是这个方法存在2个明显的问题:
-
单位时间(比如1s)很难把控,如下图:
-
这张图上,从下面时间看,HPS没有超过100,但是从上面看HPS超过100了。
-
有一段时间流量超了,也不一定真的需要限流,如下图,系统HPS限制50,虽然前3s流量超了,但是如果读超时时间设置为5s,并不需要限流。
滑动时间窗口
滑动时间窗口算法是目前比较流行的限流算法,主要思想是把时间看做是一个向前滚动的窗口,如下图:
开始的时候,我们把t1~t5看做一个时间窗口,每个窗口1s,如果我们定的限流目标是每秒50个请求,那t1~t5这个窗口的请求总和不能超过250个。
这个窗口是滑动的,下一秒的窗口成了t2~t6,这时把t1时间片的统计抛弃,加入t6时间片进行统计。这段时间内的请求数量也不能超过250个。
滑动时间窗口的优点是解决了流量计数器算法的缺陷,但是也有2个问题:
- 流量超过就必须抛弃或者走降级逻辑
- 对流量控制不够精细,不能限制集中在短时间内的流量,也不能削峰填谷
漏桶算法
漏桶算法的思想如下图:
在客户端的请求发送到服务器之前,先用漏桶缓存起来,这个漏桶可以是一个长度固定的队列,这个队列中的请求均匀的发送到服务端。
如果客户端的请求速率太快,漏桶的队列满了,就会被拒绝掉,或者走降级处理逻辑。这样服务端就不会受到突发流量的冲击。
漏桶算法的优点是实现简单,可以使用消息队列来削峰填谷。
但是也有3个问题需要考虑:
- 漏桶的大小,如果太大,可能给服务端带来较大处理压力,太小可能会有大量请求被丢弃。
- 漏桶给服务端的请求发送速率。
- 使用缓存请求的方式,会使请求响应时间变长。
漏桶大小和发送速率这2个值在项目上线初期都会根据测试结果选择一个值,但是随着架构的改进和集群的伸缩,这2个值也会随之发生改变。
令牌桶算法
令牌桶算法就跟病人去医院看病一样,找医生之前需要先挂号,而医院每天放的号是有限的。当天的号用完了,第二天又会放一批号。
算法的基本思想就是周期性的执行下面的流程:
客户端在发送请求时,都需要先从令牌桶中获取令牌,如果取到了,就可以把请求发送给服务端,取不到令牌,就只能被拒绝或者走服务降级的逻辑。如下图:
令牌桶算法解决了漏桶算法的问题,而且实现并不复杂,使用信号量就可以实现。在实际限流场景中使用最多,比如google的guava中就实现了令牌桶算法限流,感兴趣可以研究一下。
分布式限流
如果在分布式系统场景下,上面介绍的4种限流算法是否还适用呢?
以令牌桶算法为例,假如在电商系统中客户下了一笔订单,如下图:
如果我们把令牌桶单独保存在一个地方(比如redis中)供整个分布式系统用,那客户端在调用组合服务,组合服务调用订单、库存和账户服务都需要跟令牌桶交互,交互次数明显增加了很多。
有一种改进就是客户端调用组合服务之前首先获取四个令牌,调用组合服务时减去一个令牌并且传递给组合服务三个令牌,组合服务调用下面三个服务时依次消耗一个令牌。
降级
降级是指当自身服务压力增大时,采取一些手段,增强自身服务的处理能力,以保障服务的持续可用。比如,下线非核心服务以保证核心服务的稳定、降低实时性、降低数据一致性。
总结