作者|悟空聊天结构来源|是非成败转身空。青山还在,多少个太阳。——来自《三国演义》本文将讲述周瑜、黄盖、诸葛亮如何通过三国赤壁之战将服役雪崩发挥到极致。本文已收录到我的Github,点击文末阅读原文打开。给个Star~https://github.com/Jackson0714/PassJava-学习赤壁之战相传东汉末年,曹操、孙权、刘备三方争夺赤壁之位长江赤壁(今湖北蒲岐西北)老大。这就是著名的赤壁之战。一、恢复赤壁之战曹操统一北方后,南下打败了刘备。占领荆襄之地后,他想东杀孙权,于是刘备与孙权联手对付曹军八十万大军。曹操的军队大多来自北方,缺乏水战经验,很多士兵晕船,所以曹操命令军队用铁索连接船尾,以减弱风浪的湍流,有利于士兵的演练。铁链子链-图片来源网络来看看周瑜、黄盖、诸葛亮的对话:三人对话@武婚谈建筑黄盖:曹操真傻,连舟子,要是船烧了,其他的船会一起烧毁。铁链不易解,船难逃。我们用火攻,直接把曹俊安放倒在地。周瑜:但是怎么靠近他们的船呢?黄盖:我假投降,乘了几艘船,船上载着油干草就出发了。当他们接近曹军时,我点燃干草,冲向曹军的连船,点燃他们的船。周瑜:太好了!但东风从何而来?诸葛亮:我是来借东风的~赤壁之战那天,火舟乘风闯入曹军舰队,一片火海。联军乘势进攻,曹军伤亡惨重。最终,联军大获全胜,成为一场以少胜多的经典战役。链船起火-图片来源网络二、战况分析周瑜和黄盖看到了链船的弱点:“如果一艘船着火,它也会烧掉相连的船。”这与我们系统中的服务雪崩问题非常相似。假设我们的系统引入微服务思想,拆分多个服务,每个服务通过接口调用完成。看起来功能转为微服务后,功能和职责都单一了,这正是我们想要的。但是随着业务的增长,服务的数量也会越来越多,逻辑也会越来越复杂。一个服务的某个逻辑需要依赖多个其他服务来完成。如果一个依赖服务不能向上游服务提供服务,很可能会造成雪崩效应,最终导致整个服务无法访问。就好比雪山上某个地方的雪崩,慢慢带动其他地区的雪崩,产生连锁反应,最终造成大面积的雪崩。这是一个常见的雪崩场景。【总结】导致整个链路服务失效的服务故障称为服务雪崩。那么曹军应该如何避免这个问题呢?别着急,我们稍后会看到答案。3、系统中的雪崩效应微服务之间经常使用RPC或HTTP调用。一般会设置调用超时限制,或者使用失败重试机制来保证服务的成功执行。但是,如果不考虑服务的熔断和限流,还是很容易产生服务雪崩的。下面用一个例子来解释一下雪崩效应是如何产生的。雪崩效应我们的系统中有三个服务:订单服务、商品服务、库存服务。下单场景:用户下单购买商品,客户端调用订单服务生成预付费订单,订单服务调用商品服务查询订购的商品,商品服务调用库存服务判断商品是否有库存,如果有库存,可以生成预付款订单。假设双十一流量激增导致库存服务不可用(如响应超时等),库存服务收到的很多请求还没有处理,它就无法处理更多的请求。而上游商品服务依赖库存服务,会实现商品服务的超时和重试机制。不断产生新的商品服务调用会导致商品服务调用大量积压,导致大量的呼叫等待和重试调用,慢慢耗尽商品服务资源,如内存,导致商品服务宕机。而订单服务又会回到商品服务的老路子。结果是所有三个服务都不可用。4、雪崩真实场景1.4.1服务商不可用硬件故障:如网络故障、硬盘损坏等程序错误:如算法需要大量CPU计算时间,导致CPU占用率高.缓存崩溃:比如应用刚重启后,短时间内缓存失效,导致大量请求直接访问数据库,数据库不堪重负,服务不可用。闪电杀戮和大促销:服务无法在短时间内处理如此多的请求。1.4.2重试增加流量用户不断重试:比如用户看到界面没有响应,就再次操作,结果请求量翻倍。程序重试机制:比如代码中有多次重试的逻辑。失败后,几秒钟后重试。重试3次后取消重试,走异常处理分支。它还增加了请求的数量。5、如何防止雪崩方案出错:限流、主动降级、隔离后修复:熔断、被动降级6、熔断的原理和算法1.6.1熔断的概念。保险丝。当电流过大时,保险丝会熔断,以防止因电流过大而损坏电气元件,或因电流过大而导致元件过热而着火。保险丝是什么样子的?《物理公式》电功率P=I^2*R,I代表电流,当元件的电阻R不变时,电流越大,电功率越大,电功大部分由元件完成电阻是有发热的,所以电功率越大,发热越严重。(好在高中物理没忘。)放到我们的系统中,我们怎么理解融合?如果调用某个服务很慢,甚至在一定时间内超时,这个服务就可以熔断,其他服务稍后再调用这个服务。直接回去告诉其他服务:“”它坏了,不要给我打电话,稍后再试。》1.6.2如何熔断《熔断有一个原则》在一段时间内,如果统计失败的次数或者失败请求的比例超过一定的阈值,就会进行熔断。详细原理如下图所示:断路器图&悟空聊天架构1.6.3统计请求算法请求访问后台服务后,首先判断断路器开关是否打开。如果断路器打开,则表示无法处理当前请求。如果熔断器开关没有打开,则判断时间窗是否满。如果时间窗未满,则请求桶中的请求数加1。如果返回的响应有异常,则失败桶中的失败数加1,如果返回的响应是没有异常,成功桶中的成功数加1。如果时间窗已满,则开始判断是否需要熔断。1.6.4熔断器恢复算法当熔断器熔断时,开关切换到断开状态。一段时间后,开关切换到半开状态(Half-Open)。在半断开状态下,允许一定数量的应用程序请求调用服务。如果调用成功,则认为服务可以正常访问,于是将开关切换到关闭状态。如果在半断开状态下仍然有呼叫失败,则认为业务还没有恢复,交换机从半断开状态切换到断开状态。1.6.5失效率统计时间窗失效率统计时间窗@武姨话标签时间窗可以比喻为一个人坐在窗边,看着一定时间内窗外经过的车辆。对于每一个请求,都会判断时间窗口是否满了(比如5分钟)。如果时间窗口已满,则重新开始计时,并将请求/成功/失败次数清空。注意:第一次启动的开始时间默认为当前时间。1.6.6尝试恢复服务的时间窗尝试恢复服务的时间窗@吴婉话标签开关处于断开状态。一定时间后,比如1分钟,设置成半断开状态,尝试发送请求检测服务是否恢复。如果恢复,则切换状态为关闭。如果没有恢复,将状态切换为断开连接,1分钟后重复以上步骤。这里的时间窗口可以根据环境的运行情况动态调整,比如第一次是1分钟,第二次是3分钟,第三次是10分钟。7、熔断中间件有人肯定会问,你上面说的原理,这个算法真的是你自己写的吗?“回答:是的,我们在项目中造了一个轮子:熔断器。”但在这里我不建议这样做。市面上有更好的开源组件供大家使用,比如阿里的Sentinel(推荐),Netflix的Hystrix(更新)。Sentinel当然本文不讨论,后面会介绍~8.力挽狂澜曹操因为链船败北,如何给曹操提供妙计助他一臂之力扭转战局?可以使用的“有几种解决方案”麻线代替了链条,因为绳索更容易切割。(FuseMechanism)把船分成几个区域,区域之间保持一定的距离。即使一个区域燃烧,也不会影响到其他区域。(熔断+资源隔离)提前在湖上设置检查点。若是黄盖过来,先查船查人,有问题不准通行。(Fusing)9.限流降级本来想把限流降级写完这篇文章的,但是发现写的断路器的内容越来越多,所以就把限流降级放到了后面几篇.也是三国的故事~写在最后《三国演义》也是我很喜欢的文艺作品。书看了大概80%,电视剧也看完了。我最喜欢的人物当然是军事家诸葛亮,还有英雄曹操~~本文转载自微信公众号“悟空聊天建筑”,可以通过以下二维码关注。转载本文请联系悟空聊天架构公众号。
