腾讯云开发者出品
为什么要做混沌工程?
1.1 目标起点
微信支付是国家关键的信息基础设施,服务于数千万商户和数亿用户,可用性要求高于5个9。
1.2 分析:影响可用性的主要因素及解决方案
为了分析影响可用性的因素,我们对微信支付近几年的故障回顾数据(2018年至2021年)进行了分类,发现软硬件异常引起的故障占比较高(基础设施、部件、上游和下图下游部分)。
针对各种导致失败的因素,微信支付采取了相应的措施,例如
但对于软硬件故障,虽然基础组件会涉及到一些容错处理,但设计是否全面、开发是否充分实现、真实场景是否真实,没有统一的工具和验收标准来推动解决方案。有效的。
如何验证系统具备应对软硬件异常的容灾能力?我们调查了公司和行业使用的方法,其中演练和混沌工程是最常见和有效的。它们都强调在线实施,旨在提高系统的可靠性和灵活性,但方法和侧重点不同(两者概念和想法的差异对实际实施影响较大)。
1.2.1 练习
演习通常有明确的执行计划和期望,要求注入故障的影响是已知的且明确的。
更加注重人的反应和应急预案,也考虑非系统因素。例如,验证某个系统出现故障后,人为干预的过程和机制是否顺畅。
1.2.2 混沌工程
(公司和业界对于混沌工程的概念有很多介绍,如果不明白的可以先自己搜索一下,我就不赘述了。)
混沌工程更注重发现未知风险,更注重系统的灵活性,不涉及系统外的因素。混沌工程提出的五个原则是业界的普遍共识:
多种多样的项目和控制爆炸半径的方法与演习有很大不同。正是由于对爆炸半径的控制,混沌工程中断层注入的强度和复杂性远高于钻探能力。可以更全面、更真实地模拟现网故障,达到“发现未知风险”的目的。
此前,演练是微信支付容灾验证的重要手段。我们发现,由于演练没有系统的爆炸半径控制方法,演练在工具开发、监测和稳态识别、事件多样性、自动化等方面需要做更多的工作。定制开发和人工实时观察需要更多的工作。劳动力投资成本高。
因此,引入混沌工程系统来有效控制爆炸半径,更大程度地注入异常,并适当构建自动化能力来识别系统弱点并促进持续治理以提高可用性是一个值得探索的方向。
1.3 可行性
实施混沌工程存在两大矛盾:
为了贴近真实环境,注入故障越贴近真实环境就越有效,但这必然会影响业务可用性。而且,微信支付对可用性要求很高,不接受不可预测的风险。如果业务安全问题不解决,引入混沌工程“探索未知风险”的期望将难以实现。
2021年,微信商业支付进行了多分区改造,将业务流量路由到不同分区。各分区之间相互独立,互不影响。通过部署来保证分区之间的环境一致性。将故障注入分区隔离的IDC环境并分配可控流量,既可以贴近生产环境,又可以保证故障收敛,控制爆发半径。这样,微信商户支付就具备了实施 的条件和可行性。
如何实施
从业界实施混沌工程的经验来看,基本都是围绕着提出的5大原则展开的。
建立稳定状态的假设,即从用户的角度衡量业务的健康度。一般情况下,企业都有现成的业务监控,大多数情况下不需要额外开发。
使用各种现实世界事件进行验证将丰富注入故障的类型,并且自动化实验持续运行将减少人工参与的成本。两者都需要额外的开发,但先开发哪些以及能在多大程度上与业务目标结合,更重要的是开发人力成本与可挖掘的风险和收益之间的ROI考虑。
在生产环境中进行实验和控制爆炸半径最小化是混沌工程有效性和安全性的两个关键问题。
因此,实施混沌工程的主要难点是:
2.1 安全有效的实验
不同技术选择对应的有效性和安全性如下:
一般来说,有效性和安全性很难同时满足,两者之间存在一种权衡关系。越是想要真实的恢复故障,就需要在真实环境下用业务流量来模拟故障,进而影响业务安全;但如果一味追求安全而不对业务造成任何任务影响,就无法还原故障的真实场景,也很难发现问题。可以结合实验目标,确定业务可以接受的最低安全性,然后选择最有效的解决方案。
2.1.1 安全:不影响网上业务
控制爆炸半径
爆炸半径的选择也可以在混沌工程实施的不同阶段进行调整。您对系统的可用性越有信心,它就越接近真实环境。因此,前期可以在效率较低的环境中进行实验。当通过实验方法很难发现新的问题,并且发现的问题已经得到解决时,可以考虑升级为有效。更高的方案。
对于微信商业支付,如上所述,2021年已经进行了多分区改造,因此我们在多分区架构上单独规划了分区路由和4个业务分区,部署了业务逻辑模块、存储、组件等和生产分区一模一样。前期将模拟流量放入混沌分区,然后注入故障。当对系统有足够的信心时,稍后会将故障注入到生产分区中。
由于多分区只是修改了核心业务,所以还存在外部依赖服务。为了防止混沌实验对外部依赖的影响,对不同场景下的风险源进行了相应的处理:
特殊限制和批准
考虑到“数据篡改”失败可能导致写入脏数据,特别是篡改业务执行主体(如商户ID、用户ID),写入脏真实业务数据的风险,因此禁止“篡改执行主体”失败。
考虑到进行实验的风险,我们增加了对以下场景的批准:
2.1.2 有效:接近真实环境
我们主要在孤立的混沌分区中进行实验。实验环境与真实环境的一致性越高,真实环境中出现类似问题的概率就越大。
静态:部署环境的一致性
部署环境一致性的主要维度如下:
我们将一致性要求较高的地域、园区、容器、二进制文件、配置集成到部署工具中,并在模块上线和发布变更时与生产环境保持一致。
动力学:实验流量的真实性
让实验流量更接近线上的目的是为了恢复机器/容器的负载情况,恢复业务执行的分支。两者在一些复杂的组合场景下是否会引发未知的风险。我们从两个维度来评价交通模拟程度:
基于这两个指标,有两个不同的方向:
考虑到前期建设成本和不确定性,我们选择了人工流解决方案。
2.2 高效全面挖掘风险
在构建混沌工程体系以及从0到1的业务落地时,我们遇到了两类问题:
我们选择从业务目标出发,优先考虑高价值的风险点,通过与业务目标相匹配的工具逐步丰富故障原子。根据不同阶段的侧重点,项目实施路径分为两个阶段:
2.2.1 发现高价值风险
前期人力和工具有限,如何挖掘高价值风险(高ROI)?
更简单的方法是:随机注入。工具团队可以根据近年来的故障类型,按照优先级开发相应的故障原子,并无差别地注入到目标模块中。如果目前的自动进样和稳态分析还不够完善,仍然需要人工参与。这种方法有两个局限性:
业务团队的实施需要大量的人力:人工注入故障,人工观察分析业务监控,监控偏差,看是否影响业务,是否会分散风险,是否存在其他潜在风险;
工具团队无法有针对性地投入有效人力来开发最有价值的原子。
为了快速发现高价值风险,提高大家的参与热情,我们选择了以下两种策略:
1、实验对象从高值到低值覆盖。基于这一思路,得出了优先实施的模块。 1)公共组件:RPC框架、队列、存储、缓存、安全认证、日志等; 2)生命线业务:收款、付款、退款。
2、基于高可用的原则,拆解工具,获取需要开发的原子需求和需要注入的资源。
设计路径如上图所示。基于历史故障和常见的高可用需求原则,假设某个组件/业务满足高可用原则,根据这个原则,将其拆解为故障原子和需要注入的注入范围(目标),而某个业务或者组件要实现的混沌实验方案如下图:
通过这些策略,我们很快发现了微信基础组件中HTTP访问模块、事件中心、跨城组件等多个高危常见问题。
2.2.2 查找所有风险
后期如何加强覆盖,发现更多未知的黑天鹅风险?
上述方法只能覆盖有限的故障域,实际故障往往是由多个事件同时发生触发的。因此,通过后期加强单原子乱注入和组合断层注入,可以发现更多的中长尾问题。
对于组合失败,如果也是无差别策略,那么组合空间巨大。以微信支付委托扣缴业务为例:
即使该工具具有自动注入和自动分析的能力,实验周期和资源消耗也会非常高。因此,合理修剪是必要的。可以采用基于相关性从强到弱的多故障组合,例如:
2.2.3 自动化
从实验流程来看,除了“修复问题”之外,其他三个流程都可以在一定程度上实现自动化。
自动设计
一个实验任务由4部分组成:
业务资产:集群、模块、接口;集群是多个模块的总称。例如,存储集群包括访问模块、存储模块、元数据模块;
系统资源:业务资产执行所依赖的机器、容器、网络、CPU、磁盘、进程、文件、内存、共享内存等;
故障类型:每个系统资源都有多种故障,如机器重启、机器时间错误等,如网络缓慢、丢包、紊乱等。
故障程度:除了少数机器重启等0-1类故障外,其他大部分故障都涉及一定程度的故障,如网络丢包30%等。不同级别的性能略有不同。一般来说,故障程度分为几个级别。如果单机丢包为10%、30%、50%、80%、100%,则结合多机情况。
做一个实验,先圈出包含的业务资产,然后梳理其所依赖的系统资源(除了磁盘、文件、共享内存,其他的一般都包含),然后展开系统资源的故障类型,最后确定失败的程度。有两种策略:
因此,业务需要做的是:划定资产范围和依赖的系统资源,并标记资产类型或适用哪些高可用性原则,然后就可以自动生成实验任务。
自动执行
体系建设不是一朝一夕就能完成的。从手动执行到自动化我们经历了三个阶段:
自动分析
上述自动执行减少了“点击”操作的工作量。实验必须“完全”自动化,并与自动分析相结合,即自动判断是否偏离稳态。一是当稳态偏离正常范围时及时停止,避免发生次生灾害;其次,只有实现自动分析,才能实现低成本的“定时执行”。否则,每次自动执行后都依赖人工分析,这是不可持续的。
我们根据实验的时间(实验开始到实验结束的一个周期)自动匹配相关的稳态报警:
2.2.4 风险处理
除由责任人处理发现的风险外,还应采用以下方法:
性格问题:由知名人士和商业领袖处理
通过 SOA 治理、架构建模和改进的研发流程可以大规模消除常见问题,从而最大化组织价值。
针对不同时间出现的问题使用不同的策略:
成就
我们通过设计实验(构建原子)——执行实验——分析结果(挖掘问题)——修复问题的一套流程推进,在业务风险挖掘和工具构建方面取得了良好的效果。
3.1经营业绩
自2021年上线以来,线上失败0次,执行了60+个实验计划,500+个实验任务,覆盖业务、框架、组件多个场景,探索多重风险。
3.2 工具构建结果
微信支付构建了从0到1的混沌工程系统(由业务连续性架构中心和支付运维团队构建)。
支持30多种故障原子。典型原子:
页面支持拖拽排列、串并排列,可配置定时启动实验,实现常态化验证风险。
通过关联微信支付模块调用异常报警和业务监控报警,可以识别被测模块/IP中潜在的异常情况,并在实验报告中展示,提高实验后分析的效率。
总结与展望
4.1 总结
本文从业务角度介绍了混沌工程在微信支付中的实施思路。它采用多分区架构来控制最小爆炸半径。首先探索高价值的基础组件和微信支付核心业务场景,并基于高可用性原则和历史故障。错误原子的分析衍生发展。发现不少共性风险,推动修复治理。
4.2 展望
4.2.1 更丰富的故障原子构造
有效性和安全性始终是一个权衡因素。如上所述,微信支付采用独立混沌分区架构实现,前期采用模拟流量。因此,除了篡改数据类原子之外,在控制请求量的同时,注入故障的爆炸半径很小,对线路的影响极低。
但由于对业务安全的思维惯性,我们在构建有缺陷的原子时,基本遵循的是练习的思路:先了解组件原理,将原子逐个定制组件/业务,从而得到一个提前交付周期长。如果在控制爆炸半径的基础上,开放更多断层注入的自由度,注入更多、更强烈的断层,就能以较低的成本发现更有价值的风险。
4.2.2 自动化和稳态辨识
自动化包括:故障注入和异常判定。当前系统支持故障注入的自动化和简单的稳态识别。识别准确率和召回率还有空间,因此大多数异常判定仍然需要人工分析。自动异常判定需要相对先进的AI能力,并且很难根据某些特定规则覆盖所有场景。如果能够实现全面自动化,混沌工程就可以低成本地在其他业务中实施。此外,还可以注入大量组合断层,探索更多未知风险。
4.2.3 支持多种爆炸半径实验
本文在多个分区上部署独立的混沌分区来控制爆炸半径。对于大多数非核心支付或非支付业务来说,不存在多分区环境。因此,在其他业务中实施混沌工程,还是需要根据业务的安全性和有效性来做出选择。