混沌工程 - 软件系统高可用、弹性化的必由之路

随着摩尔定律的终结,单机计算性能已达到了极限,然而,咱们的软件系统不管是规模仍是复杂度一直在增加,因此软件系统都不约而同的朝着分布式化方向发展。近年来,随着云服务、容器的出现,某些分布式系统也更容易微服务化。抛开这些形形色色的分布式技术,咱们对系统可靠性的述求倒是一致的:分布式系统须要高可用,即便出现了单点或集群故障,也但愿系统具有自我恢复或优雅降级的弹性能力、容错能力。咱们在合理的架构,高质量的代码,完善的测试等等方面作了不少努力,然而不少分布式系统仍旧达不到高可用、弹性化,为了尽量发掘系统中存在的弱点,不少大型软件公司都引入了混沌工程,如国外的谷歌、网飞,国内的京东等等。哪些能够称之为系统弱点呢,好比git

  • 外部系统故障,致使内部系统连锁故障,我司即出现过由于七牛服务故障致使的内部故障
  • 服务不可用时,不合适的降级方案
  • 不合适的超时机制,致使请求错误时无限次重试

混沌工程的定义:

经过观察分布式系统在受控的故障注入测试中的行为变化发掘系统弱点,并针对性的改进,从而提升系统可靠性,创建系统抵御失控条件的能力的信心。因此,混沌工程并非一个新概念,常见的异地容灾测试也是混沌工程的一种应用。github

混沌工程的通常实施步骤

  • 寻找一些系统正常运行状态下的可度量指标,做为基准的“稳定状态”
  • 假设实验组和对照组都能继续保持这个“稳定状态”
  • 对实验组进行事件注入,如服务器崩溃、硬盘故障、网络链接断开等等
  • 比较实验组和对照组“稳定状态”的差别,推翻上述第2条的假设

若是混沌工程实施下来二者的“稳定状态”一致,则能够认为系统应对这种故障是弹性的,从而对系统创建更多信心。相反的,若是二者的稳定状态不一致,那咱们就找到了一个系统弱点,从而能够修复它,提升系统可靠性。sql

混沌工程的理想原则:

1)根据“稳定状态下系统的特征”作一个假设

以电商下单为例,下单系统可能包含了商品服务,交易服务,支付服务,“假设”不是着眼于各个“螺丝钉”服务的具体状态,而是着眼于整个下单系统正常运做下的外部状态,以下单量、成交金额、系统吞吐量、延时、错误率等等,这些指标通常会有大盘监控,并且除非遇到促销活动,这些指标曲线通常不会大起大落,其变化趋势是能够预期的。可是有一点须要特别注意,某些问题虽然不会怎么影响大盘数据(如缓存失效、一个CDN节点失效等等),可是咱们仍旧须要监控系统中各个节点的微观指标(如CPU、IO等)以期发现这类问题(缓存失效可能致使Mysql集群压力增大,CPU/IO等压力变大)。缓存

2)事件是现实世界真的可能发生的

任何可能影响系统稳定状态的均可以做为事件,常见的,如服务器

  • 故障类:像服务器宕机、断网等硬件故障,像七牛等外部服务不可用的软件故障
  • 非故障事件:像流量激增

咱们还能够分析曾经引发系统故障的事件的种类和频次,针对性的排列优先级,并实施这些事件,避免系统再次出现这种故障。网络

3)在生产环境跑

根据第1条,通常只有生产环境的指标是可预测的,如新用户日注册量,用户日下单量。并且,因为测试环境和生产环境不可能如出一辙,为了真实反映系统的可靠性,通常推荐在生产环境实施混沌工程。架构

4)持续集成

互联网软件天天都在更新,因此像跑持续集成同样实施混沌工程具备现实意义。异步

5)最小化影响范围

根据第3条,混沌工程可能致使线上功能不可用,甚至形成资损,因此在以找出系统弱点为目的的前提下,须要最小化故障影响范围,而且当出现严重问题时能够迅速恢复,即故障是可控的。鉴于此,有时候能够引入A/B测试,最小化影响范围。tcp

上面是最理想状况下的混沌工程,现实中咱们须要根据现有软件成熟度有阶段的实施混沌:分布式

阶段一:分布式系统弹性化通常

  • 以京东为例,他们会在双十一大促以前进行故障演练,将团队分为两组,一组做为故障的制造者,另一组做为故障的解决者和响应者,来考察故障发生的时候,团队对故障的检测、响应、处理还有恢复能力。达到小的故障不须要人介入,大故障人工介入能够快速处理的目的。经过在大促以前的两个月期间密集的开展混沌工程,提升团队对大规模故障的容错能力。

  • 以有赞为例,因为咱们才刚刚开始,为了控制风险,起初只会在测试环境实施混沌工程,因此暂时没有能够参考的准确大盘数据,即合适的基准“稳定状态”。但也不是不可能,观察大盘数据能够认为反映的是系统宏观指标,从微观角度来说,咱们能够筛选出一批直接影响核心大盘数据(如注册量、下单量等)的接口,在对系统实施混沌后执行这些接口的场景化集成测试,经过观察测试结果来评估系统的可靠性,从而寻找系统弱点,这在测试环境是可行的。
    此外,混沌工程能够认为是通用型异常不定时不定目标不定异常类型的自动化实现,若是抛开这层,手动对目标机器注入特定的一种或多种异常,并辅以对应的异常恢复手段,那咱们就能够在通用异常测试中应用。

阶段二:分布式系统弹性化成熟

  • 以网飞为例,他们基本上已经在按照上述理想的步骤和原则实施混沌工程,工做日持续、自动的实施混沌工程,系统具有高度的可靠性,弹性伸缩。

有赞混沌工程的实现:

因为混沌工程主要是注入特定的事件并引发系统故障,既然是“干坏事”的,因此咱们将其命名成了“威震天”(变形金刚中的反派Boss)。因为咱们还处于第一阶段,因此故障的注入主要是人为控制,目前已实现的故障类型有:

  • CPU高负载
  • 磁盘高负载:频繁读写磁盘
  • 磁盘空间不足
  • 优雅的下线应用:使用应用的stop脚本平滑的中止应用
  • 经过kill进程直接中止应用,可能形成数据不一致
  • 网络恶化:随机改变一些包数据,使数据内容不正确
  • 网络延迟:将包延迟一个特定范围的时间
  • 网络丢包:构造一个tcp不会彻底失败的丢包率
  • 网络黑洞:忽略来自某个ip的包
  • 外部服务不可达:将外部服务的域名指向本地环回地址或将访问外部服务的端口的OUTPUT数据包丢弃

参考文献
PRINCIPLES OF CHAOS ENGINEERING

个人其余博客
异步系统的两种测试方法

个人开源项目 —— 方便产品、开发、测试三方协同自测的管理工具
捉虫记

ps: 有赞测试组在持续招人中,大量岗位空缺,只要你来,就能帮你点亮全栈开发技能树,有意向换工做的同窗能够发简历到 sunjun【@】youzan.com