微服务1:微服务及其演进史
微服务2:微服务全景架构
微服务3:微服务拆分策略
微服务4:服务注册与发现
微服务5:服务注册与发现(实践篇)
微服务6:通信之网关
微服务7:通信之RPC
微服务8:通信之RPC实践篇(附源码)
微服务9:服务治理来保证高可用
1 为什么熔断限流
分布式系统环境下,服务间类似依赖非常常见,一个业务调用通常依赖多个基础服务。
如下图,对于同步调用,当库存服务不可用时,商品服务请求线程被阻塞,当有大批量请求调用库存服务时,最终可能导致整个商品服务资源耗尽,
无法继续对外提供服务。并且这种不可用可能沿请求调用链向上传递,这种现象被称为雪崩效应。
1.2 雪崩效应常见场景
- 硬件故障:如服务器宕机,机房断电,光纤甚至专线被破坏等。
- 流量激增:如异常流量,线上活动导致的流量激增,重试导致流量放大等。
- 缓存穿透:缓存服务重启,导致大量缓存同时失效时。重建缓存或者大量的请求无法命中缓存,会直接投向数据库,导致服务和数据层压力骤增甚至雪崩。
- 程序漏洞:如程序逻辑(如死循环)导致内存泄漏,或者死锁操作导致互相等待,或者JVM长时间FullGC等。
- 同步等待:服务间采用同步调用模式,同步等待造成的资源耗尽。
1.3 雪崩效应应对策略
针对上述的常见场景,需要给出不同的策略来应对,主要有如下几个方面,参考如下:
- 硬件故障:分服甚至分机房容灾、异地多活等。
- 流量激增:服务动态扩缩容,流量控制(熔断,限流,超时重试)等。
- 缓存穿透:缓存预加载、异步加载,设置不定的过期时间等。详细参考这篇《一次缓存雪崩的灾难复盘》
- 程序的健壮性:修复程序漏洞、避免内存泄漏、及时释放资源 等等。
- 同步等待:资源隔离、MQ解耦、不可用服务调用快速失败(超时能力)等。
综合上述的内容可知,如果一个服务不能对自己依赖以及产生的故障进行隔离,那么它自己本身就会处在雪崩风险中。要想构建稳定健壮的分布式系统,我们的服务应当具有自我保护能力和容错的能力。
避免造成更大的故障设置服务雪崩。而这种自我保护的模式就是熔断、限流、异常驱逐等能力。
2 常见的限流的算法
2.1 计数限流算法
计数算法是指再一定的时间间隔里,记录请求次数,当时间间隔到期之后,就把计数清零,重新计算。如果请求次数超过统计周期内额定的最大次数时,直接拒绝访问,简单粗暴。
计数器的值要是存在内存中就算单机限流算法,类似 Atomic 等原子类。如果存放在类似Redis的第三方缓存服务服务中就是分布式限流了,类似 Redis incr、Redis decr。
如下图所示:
可能存在的问题是:请求分布的不均衡,比如在时间周期1分钟的第1秒,就把100次请求用完了,那么最后59秒都是空白的。也可能直到最后1秒才有大批量的流量
涌入,造成系统的不稳定。
2.2 固定窗口限流算法(采样时间窗)
![微服务12:系统服务熔断、限流](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)
固定窗口计数算法的步骤是:
- 将时间划分为固定的时间窗口,比如1s。
- 在窗口时间段内,每来一个请求,对计数器加1。
- 当计数器达到设定限制后(比如上图,限制了5s),该窗口时间内的之后的请求都被直接拒绝了。
- 时间窗结束后,计数器重置,重新开始计数。
2.3 滑动窗口限流(记录每个请求到达的时间点)
滑动窗口限流解决固定窗口临界值的问题,可以保证在任意时间窗口内都不会超过阈值。
相对于固定窗口,滑动窗口除了需要引入计数器之外还需要记录时间窗口内每个请求到达的时间点,因此对内存的占用会比较多。
上图中每个时间窗口限流8个req,滑动窗口计数算法的步骤如下:
- 将一个时间窗口划分为细粒度的区间,每个区间配置一个计数器,每incr一个请求则将计数+1。
- 因为一个时间窗口是由多个时间区间组成,每走完一个区间时间后,则抛弃最老的一个区间,纳入新区间。如上图抛弃区间1,纳入新区间3
- 窗口由t1 过渡为 窗口t2。
- 若当前窗口的区间计数器总和超过额定的限制数量8,别区间2使用了5,则区间3最多只能使用剩下3个,后续请求都被丢弃。
2.4 漏桶算法(漏斗池算法)
类似沙漏思维,大家都用过,沙子是匀速流出得。对于漏桶来说,由于它的出水口的速度是恒定的,也就是消化处理请求的速度是恒定的,所以它可以保证组件以恒定的速率来处理请求,
这对一些对处理速度或者资源有严格要求的系统是非常实用的。原理如下:
- req到来则放入桶中
- 桶内请求量满了,则拒绝后续的请求
- 服务定速地从桶内拿出请求并处理
宽进严出是它最大的特点,无论请求多少,请求的速率有多大,都按照固定的速率流出(定速输出),而服务也只能按照固定速率处理,有点像固定延时的消息队列。
如果有处理不过来的请求,那就按照队列进行排队,避免巨大输出把服务搞挂掉,队列满了就refuse。
![微服务12:系统服务熔断、限流](http://www.itfaba.com/wp-content/themes/kemi/images/loading.gif)