在企业业务领域,锦礼是针对福利、营销、激励等员工采购场景的一站式解决方案,包含面向员工、会员等弹性激励SAAS平台。由于其直接面向公司全体员工,其服务的高可用尤其重要,本文将介绍锦礼商城大促前夕,通过混沌工程实战演习,降低应用的MTTR。
MTTR(平均恢复时间)是从产品或系统故障中恢复所需的平均时间。 这包括整个中断时间——从系统或产品出现故障到其恢复完全运行为止。
如何在混沌演练的场景中降低应用的MTTR,必须需要根据监控定位,然后人工进行反馈进行处理吗?是否可以自动化,是否有方案可以降低混沌演练过程中的影响?以此达到快速止血,进一步提高系统的稳定性。
本篇文章将根据一些思考和实践来解答以上问题。
故障无处不在,而且无法避免。
我们将从宿主机重启问题以及底层服务混沌演练的排查与举措说起。
通过定位发现大促备战前期宿主机重启及底层服务混沌演练原因,较长时间影响我侧系统可用率及性能。尤其是核心接口的部署应用,会大范围的影响到多个接口的可用率,进一步影响采购端客户的体验问题。
特别在TOB领域,本身就存在大客户的口碑效应,如果恰好头部客户碰到该问题,那么极易被放大和激化。
一方面协同运维组确认宿主机重启未及时通知的情况,另一方面与底层服务提供者同步演练影响,建议其遵守演练原则最小化爆炸半径,控制影响范围,保证演练是可控的。
除了以上协同外部的情况外,我们内部也产生了思考,首先情况故障本身就是不可控的,无论宿主机还是混沌演练,真实场景也是有概率发生的(并且已发生)。那么我们只能通过监控定位,然后手动摘除机器或者通知服务提供者处理吗?是否可以自动化,是否有方案可以降低影响?以此达到快速止血,进一步提高系统的稳定性。
既然无法避免故障,那么就拥抱故障,通过一些技术手段来构建获取应用故障的能力,从而保证应用的高可用。
由于内部的调用90+%为(JSF)RPC调用,所以我们还是把目光放到了JSF中间件的容错能力上,以下主要介绍通过JSF中间件的超时与重试、自适应负载均衡、服务熔断来进行故障转移的理论与实践。
实践是检验真理的唯一标准。
实际开发过程中,相信大家也见过太多由于超时未设置、设置有误导致的故障。当超时未设置或者设置不合理,会导致请求响应变慢,慢请求的不断累计叠加,就会引起连锁反应,甚至产生应用雪崩。
不仅我们自身的服务,还有外部的依赖服务,不仅HTTP服务,还是中间件服务,都应该设置合理的超时重试策略,并且重视起来。
首先读写服务的超时重试策略也是大不相同的,读服务天生适合重试(如设置合理超时时间后重试两次),但是写服务大多是不能重试的,不过如果均是幂等设计,也是可以的。
另外设置调用方的超时时间之前,需要先了解清楚依赖服务的TP99响应时间是多少(如果依赖服务性能波动大,也可以看TP95),调用方的超时时间可以在此基础上加50%Buff。当然服务的响应时间并不是恒定的,在某些长尾条件下可能需要更多的计算时间,所以为了有足够的时间等待这种长尾请求响应,我们需要把超时设置足够合理。
最后重试次数不宜太多(高并发时可能引发一系列问题(一般2次,最多3次),虽然重试次数越大,服务可用性越高,但是高并发情况下会导致多倍的请求流量,类似模拟DDOS攻击,严重情况下甚至于加速故障的连锁发生。因此超时重试最好是和熔断、快速失败等机制配合使用,效果更佳,这个后面会提到。
除了引入手段,重要的是验证手段的有效性。
模拟场景(后续另两个手段也是用该场景)
方案:采用故障注入(50%机器网络延迟3000-5000ms)的方式模拟类似场景,并验证。
机器部署如下:
正常情况(未注入故障)
注入故障——超时设置不合理情况下(超时2000ms,重试2)
该接口TP99在6ms,设置超时10ms,重试2。即:jsf:methodname="queryActivityConfig"timeout="10"retries="2"/
在接口维度拆分不合理的情况下,我们可以更细粒度的使用方法维度的超时重试配置,不过这里有一个注意项JSF当前注解方式不支持方法维度的超时重试设置,仅支持接口维度,如已使用注解类,可进行迁移XML方式进行配置使用。
对于shortestresponse自适应负载均衡设计目的是解决在 provider 节点能力不均的场景下,让处理能力较弱的provider少接受些流量,不会因个别性能较差的 provider 影响到 consumer 整体调用的请求耗时和可用率。
能者多劳拙者闲,智者多忧愚者无所虑。
但是该策略下也是存在一些问题的:
现有的shortestresponse的实现机制,类似P2C(Power of Two Choice)算法,不过计算方式不是采用当前正在处理的连接数,而是默认随机选择两个服务提供者参与最快响应比较计算,即:统计请求每个provider的请求耗时、访问量、异常量、请求并发数,比较平均响应时间 * 当前请求数,用于最快响应负载计算。选取优胜者来避免羊群效应。以此自适应的衡量 provider 端机器的吞吐能力,然后将流量尽可能分配到吞吐能力高的机器上,提高系统整体服务的性能。
略
注入故障(设置自适应负载均衡)
当电路发生短路或严重过载时,熔断器中的熔断体将自动熔断,对电路进行保护。避免对设备产生重大影响,甚至火灾。
服务熔断是面向不稳定服务场景的一种链路保护机制。
其背后的基本思想非常简单,将受保护的函数调用包装在熔断对象中,该对象会监视故障。当调用链路的某个服务不可用或者响应时间太长导致故障达到设定阈值时,会进行服务熔断,熔断窗口内不再有该节点服务的调用,以此来最大限度避免下游服务不稳定对上游服务带来的影响。
略
能力只是手段,稳定性才是目的。
无论采用什么手段,进行稳定性建设,我们需要时刻思考的是如何在业务需求和稳定性建设中寻找平衡,以建设支持业务长期增长的高可用架构。