从2005年Peter Rodgers博士提出微web服务,到2014年ThoughtWorks首席科学家Martin Fowler与James Lewis共同提出微服务概念至今已多年,这期间也是互联网及互联网+发展的高速期,消费市场变化莫测,消费者也变得越来越挑剔,很多公司和产品由于无法跟上市场的快速变化而纷纷倒下。越来越多的互联网巨头甚至传统行业都开始对自己的遗留系统进行微服务改造,通过把系统拆分为更加灵活、有业务边界上下文、松散耦合、可独立部署的服务来应对快速变化的消费市场。
通常情况下,对于复杂业务或遗留系统,我们可以通过领域驱动设计(DDD:Domain-Driven Design)有效的解决限界上下文划分、服务边界定义以及组织结构调整等问题。除了这些,我们的开发团队还面临着其他的挑战:复杂的分布式系统、数据一致性、容错设计、限流设计、舱壁设计等问题。那么如此复杂的系统如何来保证系统“质量”呢?
长久以来,“测试金字塔”都是敏捷开发团队保证项目交付质量的守则,而“测试金字塔”也确实从不同的维度涵盖了方法调用、业务逻辑、用户行为等方面。为了确保在进行复杂的调用和被调用时,服务之间能有一定程度上的一致性和快速反馈,我们会第一时间想到“契约测试”,“测试金字塔”也演化成了另一个样子。
下图,我们聚焦于微服务架构的业务服务层,在API测试之外在基础服务的调用方和提供方之间增加了契约测试:
在微服务和前后端分离日趋流行的今天,契约测试的确可以在系统频繁演进、重构的情况下保证服务间调用的可用性,而在“聚合服务层”通过API测试,可以暴露服务的组合过程中的问题。“尽早测试”可以让团队在初期发现更多的问题,降低后期修复成本,同时让服务与服务之间具有“感知力”,任何与契约不符的业务变更都能被测试所感知。但是,既然契约测试是保证服务调用方和提供方的一致性,更直接说,是另一种对API的验证,那么契约测试只能覆盖到业务逻辑维度,如果想更好开发或改造微服务系统,就需要相对深入的了解微服务有哪些特性:
我们可以看到,这个简单的图中提到了一些微服务的特性(基于Spring Boot):客户端负载均衡、微服务容错保护、API服务网关、分布式链路跟踪等,我们不对这些进行解释,但毫无疑问,契约测试无法覆盖和测试到这些特性,同时也无法模拟例如网络延迟、CPU满载、请求异常、依赖故障、硬件故障等场景。对于一个不具备容错能力的脆弱系统,即使我们可以对服务解耦、独立部署,可对于用户来说,体验到的可能是一次又一次的“灾难”。我们在质量活动中,总会听到这样的声音:“不要动这个功能,会弄坏其他功能”、“客户根本不会这么操作“、”这个缺陷没有意义,你这样会把系统弄挂”。我们总是担心系统某些脆弱的环节挂掉,担心某次操作让整个系统宕机。遗憾的是,墨菲定律告诉我们,“如果事情有变坏的可能,不管这种可能性有多小,它总会发生。”
之前一个发生在身边的项目经历大概是这样的:一个团队提供基础服务,并承诺服务的功能、性能、弹性都没有问题。在集成联调时,由于对认证服务的调用超过负荷,对整个服务系统造成阻塞,导致雪崩效应,几乎所有客户端应用大面积瘫痪;另一个案例,由于没有对一个内容服务进行熔断保护,导致整个网站首页无法加载。而发生在世界各地的IT灾难也不少,某航空公司,由于调度和跟踪系统出现问题,导致去年6月份七天内将近3000个航班取消,损失3500万美金;“信息灾难总是普遍而没有偏见地发生在各个领域和任何时候”。
既然我们没有办法避免灾难的发生,最好的办法就是“探索系统故障边界,验证系统灾难恢复能力”。以往的“机房”时代的一些故障演练一般通过断网、断电模拟单点故障,来测试系统的恢复能力,而新型的分布式服务时代消除了单点故障,但也引入了更多复杂的问题,我们需要可靠性更强、容错性和扩容性更高的系统。一种解决方案就是,我们需要一种有策略的、有方法的实践方案对系统进行一定程度的“随机破坏”,通过让系统”感染“,来提升系统的”免疫力“。Netflix开发出Chaos Monkey来对系统进行随机试验来了解系统是否具有高可用性和容错性,而由此便诞生出”混沌工程“。
混沌工程是一种可试验的、基于系统的方法来处理大规模分布式系统中的混乱问题。通过不断试验,了解系统的实际能承受的韧性边界并建立信心,通过不同的试验方法和目的,观察分布式系统的行为和反应。一句话—— 以试验的方法尽早揭露系统弱点 。
混沌工程类似于“故障演练”,不局限于测试,而更像是工程实践。为什么这么说,通常的测试用例会有“期望结果”和“实际结果”,通过将两个结果比较,或者对用户行为的预期,来判断测试通过或失败。而混沌试验类似于”探索性测试“,试验本身没有明确是输入和预期结果,通过对系统和服务的干预,来观察系统的”反应“。我们将混沌工程原则融入在试验过程中:在生产环境小规模模拟系统故障并定期自动化执行试验,通过试验结果与正常结果进行比对,观察系统”边界“。
通过“测试金字塔”和混沌试验,从业务逻辑和系统高可用性两个维度对微服务系统进行观察和测试,两种方案结合形成了一种更全面的实践,我称之为“服务级质量内建实践”( BQIS——Build Qualify in Services )。不论企业是在微服务改造期还是中台战略部署期,混沌实践能够有效避免生产环境灾难,提升系统的容错率和可用性。
在众多服务化改造案例中,Netflix无疑是最成功的公司之一,该公司的很多试验工具也都集成在Spring Cloud中,成为微服务框架的标准。而Chaos Monkey就是Netflix进行混沌试验一个重要工具。作为国内的电商巨头,服务化和中台战略的先行者阿里,近期也开源了他们自己的混沌试验注入工具ChaosBlade。
“混沌工程”的引入受限于组织文化的接受程度,任何一种工程实践和方法论的落地都无法一蹴而就。但是我们依然可以通过裁剪,在组织的安全范围内进行逐步尝试。不管是在线上环境还是测试环境,我们都需要先搞清楚,目前的混沌工具都为我们提供了哪些方法。
Spring Cloud是时下最流行的分布式微服务架构下的一站式解决方案之一,它方便快速的将Spring Boot的微服务有效的管理起来,并提供了包括负载均衡、全链路监控、服务网关以及众多基于Netflix的开源工具。除此之外,鉴于Netflix在服务化演进中的成功案例,我们来了解下Netflix开源的混沌工程试验框架Chaos Monkey究竟是什么?
在Spring Boot工程中,对需要进行试验的服务application.yml文件的Chaos Monkey进行配置:
从配置文件中我们可以很容易看到,Chaos Monkey的三种袭击方式——延时、异常和进程终止,同时我们也可以设置一个数值范围,在对服务进行延时攻击时生成随机延时。默认攻击方式为延时攻击,当同时开启异常攻击时,进程攻击则不会发生。Level:N表示第N个请求将被攻击,N=1时,表示每个请求都会被攻击,当同时开启异常攻击时,与N值无关,表示每个请求都将被攻击。
ChaosBlade提供的攻击也很丰富,使用方式对开发人员来说更友好:
通过命令行对CPU、硬盘、网络进行试验,也可以对相应的服务进行类似的例如延时攻击试验:
利用性能测试工具例如Jmeter或Gatling,对于API进行测试,例如POST /product?des=phone,通过性能测试报告对比API性能指标以及Hystrix监控分析相关服务“反应”,同时也可以通过Grafana和CloudWatch监控各个系统参数来和“稳定基线数据”进行比较和观察。
1.确定目标和范围,观察CPU利用率基线:(CPU平均利用率低于20%)
观察API延时基线:(可以看到API-1和API-2平均延时低于300ms,API-3在300ms-700ms之间)
2.设计实验数据和方案,我们对几个实例进行CPU满载攻击:
观察CPU利用率:
观察API延时:(API请求延时变化明显,API-3延时更加严重)
示例项目架构:Eureka服务发现注册,一个PROVIDER-SERVICE且有两个实例,一个CONSUMER-SERVICE,也可以通过zipkin之类的分布式跟踪系统也可以看到服务调用关系。
1.对PROVIDER-SERVICE的实例2进行延时攻击:
2.查看PROVIDER-SERVICE instance 2的延时是否生效。通过postman测试,可以看到API响应为30s:
3.客户端请求相同的API:
观察结果:负载均衡生效,请求成功,熔断器关闭
4.杀掉instance 1之后请求相同API:
观察结果:请求超时,熔断器关闭
5.连续且请求相同API:
观察结果:部分请求被立刻拒绝,加速服务失败的判定,熔断器开启
6.杀掉instance 2请求API:
观察结果:fallback机制生效,返回相应逻辑。
这些只是混沌工程的简单使用方法,在实际项目中需要根据项目架构、业务复杂度、调用场景等设计试验细节。
从业务的横切面到对微服务系统的纵切面观察,“契约测试”固然重要,但并不能代表微服务质量保证的全部。“蛮力”可以从某种意义上解决很多问题,但并不能催化出更高阶解决方案。同样,也只有了解到微服务的实现方式和原理才能够更好的理解系统并实施更有效的质量解决方案。
Netflix对混沌工程的成熟度从“复杂度”和“接受度”两个方面给出了定义,可以看到,混沌工程或试验不单单是方法论的引入,更是实践上的渗透。用“immersion”解释更加确切,与敏捷实践类似,这样的“服务级质量内建试验”对团队来说开始无疑是一种挑战,但随着越来越多的问题更快、更早的可视化给团队,使组织和客户对我们构建和改造中的系统越来越有信心。通过小规模实践到大规模改造,混沌工程不是为了测试,更不是为了引入工具, 混沌工程会像一种文化,将扩散于范围更广的团队和组织。