滚滚长江东逝水,浪花淘尽英雄。 是非成败转头空。青山依旧在,几度夕阳红。 -- 来自《三国演义》
本篇将会通过三国中的赤壁之战
来讲述周瑜、黄盖和诸葛亮是怎么把服务雪崩
玩到极致的。
本文已收录到我的 Github,点击文末的阅读原文打开。给个Star吧~
https://github.com/Jackson0714/PassJava-Learning
话说东汉末年,曹操、孙权、刘备在赤壁市进行了一次争夺老大位置的大战,这就是有名的赤壁之战
。
曹操统一北方后,南下打败了刘备,占领荆襄之地后,还想干掉东边的孙权,于是刘备和孙权一起联合抗击曹军八十万大军。
曹操的军队大部分都是北方的,对于水上作战的经验非常欠缺,而且很多士兵晕船,于是曹操命令军队将船尾用铁索相连
,减弱了风浪颠簸,利于士兵演练。
铁索连环-图片来源网络
我们来看看周瑜、黄盖、诸葛亮的对话:
黄盖
:曹操是真的蠢啊,把船连着,如果船烧着了,其他船会跟着一起烧着的。锁链不易解开,船都逃不了了。我们用火攻,直接把曹军干趴下。周瑜
:但如何接近他们的船呢?黄盖
:我用诈降带几艘船出发,船上载浸油的干草,等接近曹军时,点燃干草,冲向曹军的连环船,引燃他们的船只。周瑜
:妙啊!可是哪来的东风?诸葛亮
:我来借东风~
赤壁之战那天,火船乘风闯入曹军船阵,顿时一片火海。联军乘势攻击,曹军伤亡惨重,最后以联军大胜结束。以少胜多的经典战役。
引燃连锁船-图片来源网络
周瑜和黄盖看出了连环船的弱点:如果一只船被烧着了,也会把连着的船烧着 。
这就很像我们的系统中出现的服务雪崩
问题。
假定我们系统引进了微服务的思想,将多个服务进行拆分,每个服务都是通过接口调用来完成的,看似功能通过微服务化后,功能和职责单一,正是我们想要的.
但随着业务的增长,服务的数量也是随之增多
,逻辑也会更加复杂
,一个服务的某个逻辑需要依赖
多个其他服务才能完成。假如一个被依赖的服务不能向上游的服务提供服务,则很可能造成雪崩效应
,最后导致整个服务不可访问
。
就像雪山上某一处出现积雪崩塌的现象,慢慢地带动其他片区的积雪崩塌,产生了级联反应,最后造成大片的积雪崩塌,这就是常见的雪崩场景。
小结: 一个服务失败,导致整条链路的服务都失败的场景,称为服务雪崩。
那曹军应该怎么避免这个问题呢?别急,后面再看答案。
微服务之间往往采用 RPC 或者 HTTP 调用,一般都会设置调用超时的限制,或者通过失败重试机制来确保服务成功执行。但如果不考虑服务的熔断和限流,还是很容易产生服务雪崩的。下面用例子来讲解下雪崩效应是怎么产生的。
雪崩效应
订单服务
、商品服务
、库存服务
。出问题前预防he:限流、主动降级、隔离
出问题后修复:熔断、被动降级
本篇主要来讲解熔断机制。 后续几篇会讲解其他方案。
保险丝熔断
熔断这个概念来源于电路系统中的保险丝
熔断。当电流过大时,保险丝熔断,防止因电流过大
损坏电器元器件,或因电流过大,导致元器件热度过高,发生火灾。
保险丝长啥样
物理公式: 电功率 P = I^2 * R,I 代表电流,元器件的电阻 R 不变的情况下,电流越大,电功率约大,电阻做的电功大部分都用来发热
了,所以电功率越大,发热约严重。(还好高中物理没忘。)
放到我们系统中,怎么理解熔断?
如果在某段时间内,调用某个服务非常慢甚至超时,就可以将这个服务熔断,后续其他服务再调用这个服务就直接返回,告诉其他服务:“已经熔断了,你别调用我了,过段时间再来试下吧。”
熔断有个原则: 一段时间内,统计失败的次数或者失败请求的占比超过一定阈值,就进行熔断。
详细的原理如下图所示:
熔断原理图&悟空聊架构
断开状态
。半断开状态
(Half-Open)。半断开状态下,允许对应用程序的一定数量的请求可以去调用服务,如果调用成功,则认为服务可以正常访问了,于是将开关切换为闭合状态
。断开状态
。时间窗口又分为固定窗口和滑动窗口。
固定时间窗口:
原理:固定时间内统计流量总量,超过阀值则限制流量。
缺陷:无法限制短时间之内的集中流量。
滑动窗口原理:
原理:统计的总时间固定,但时间段是滑动的。
缺陷:无法控制流量让它们更加平滑
时间窗口的原理图在这里:
统计失败率的时间窗口@悟空聊架构
尝试恢复服务的时间窗口@悟空聊架构
肯定有人会问了,你这上面讲的原理,难道还真的自己去写这套算法?
答案:是的,项目中我们自己造了一个轮子:熔断器。
但这里我不推荐大家这么做。市面上还有更优秀的开源组件供大家使用,比如阿里系的 Sentinel
(推荐),Netflix 的 Hystrix
(已停止更新,维护阶段)。
Sentinel 和 Hystrix 的对比,可以看这篇:双 11 的狂欢,干了这碗「流量防控」汤
曹操大败是因为连锁船的原因,那如何给曹操提供一妙计
,助他扭转战局呢?
方案有如下几个:
秒啊
对请求的流量进行控制, 只放行部分请求
,使服务能够承担不超过自己能力的流量压力。
常见限流算法有三种:时间窗口、漏桶算法、令牌桶算法。
原理:按照一个固定的速率将流量露出到接收端。
缺陷:面对突发流量的时候,采用的解决方式是缓存在漏桶中,这样流量的响应时间就会增长,这就与互联网业务低延迟的要求不符。
原理:一秒内限制访问次数为 N 次。每隔 1/N 的时间,往桶内放入一个令牌。分布式环境下,用 Redis 作为令牌桶。原理图如下:
总结的思维导图在这里:
《三国演义》也是我非常喜欢的一部文学作品,书大概看了 80 %,电视剧是看完了的。
最喜欢的角色当然是军师诸葛亮啦,国服诸葛在此!