在之前的文章中,我们聊了关于单体微服务的测试策略,有读者反馈想知道从宏观上微服务的测试策略要如何进行,本文就来探讨一下这方面的思考。
01
微服务指的是技术层面的服务细化,并不是业务层面的变革。
所以,测试微服务应用程序与测试使用任何其他体系结构构建的应用程序没有什么不同,原来的那套测试理论,还是适用的。
我们暂时把微服务看成是一个较大体系的“黑盒”,因为业务上没有变化,所以我们原来熟悉的等价类、场景法、探索性测试等测试策略还是可以照样执行,没有太多需要做出改变的,因为业务没有太大的变化。需要注意的是,基于风险的测试策略可能会发生一些变化,因为风险因素变多了,需要考虑的影响因子变多,风险分析、评估需要考量更多的内容而已。
02
好了,我们现在再把“黑盒”打开,看看微服务的技术架构给测试带来了哪些新的风险。我们需要针对这些新的挑战做出一些不一样的策略。
微服务的稳定性:在单体架构中,业务的封装调用是基于函数来进行的,几乎不存在调用失败的情况。也不会存在版本不致的情况(都在一套代码内)。但是拆成微服务后,就会面临两个问题。
第一,服务依赖得不可控:因为微服务都是可以被独立部署的,那么部署的版本就会变得不可控,那就意味着可能你调用的接口版本会发生变化,导致调用失败(这类问题会在下次的文章中重点介绍,契约测试是个不错的解决方案)。
第二,连接调用存在失败风险:微服务之间的通信要么基于Rest,要么基于RPC,都会有可能因为网络波动导致调用失败,从而引发业务问题。
针对这个问题,通常采用的策略做好微服务的版本管理,在调用链路上配置版本依赖关系,做到环境的复用。如果做不到,那就从物理上做隔离即可,尽可能缩小影响范围。
微服务的可用性:在单体构架中,代码的可用性依赖于整体的性能表现,如果某个代码段出现性能问题,会影响整体的业务表现,比较容易被发现。但是在微服务中,我们无法有效地获取其他微服务的运行状态,这就需要有统一的组件来管理,通常情况下是Hystrix与Sentinel(当然还有其他的选择,看团队的技术选型)。处理的方式有两种:熔断、降级。
熔断指的是当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用。
降级指的是:服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度。
针对这个问题,测试策略主要集中在机制的配置与生效验证上,如何保障配置的熔断降级机制能够有效,是测试的重点和难点。一般会通过性能压测来模拟。
数据一致性问题:当前面两种情况发生后,就有可能导致各微服务之间的数据不一致,从而影响业务。比如在购物的流程中订单支付成功,但调用库存服务时失败,就可能出现产品超卖的情况(订单数大于库存数)。这种场景下,一般在技术设计上会有相应的事件补偿和回调机制,来确保各方数据的一致性。
针对这个问题作为测试,需要了解这些机制的触发条件,并验证是否合理。同时,在设计测试用例时,需要关注跨系统的数据一致性验证,不能只关注自己测试的服务。
错误信息的排查:在单体架构中,当业务发生错误时,我们直接查看业务日志文件即可发现问题。但是在微服务的场景下,测试人员往往无法判断是哪个服务发生了错误,不可能每个组件一个个找过去。这就需要有统一的日志存储服务来处理。常见的技术实现是ELK平台(Elasticsearch、Logstash 和 Kibana组合),更友好的,可能还会有链路跟踪系统(OpenTracing或者SkyWalking)。在这方面,测试能做的不多,更多的是依赖基础技术的沉淀(不要想着自己搞定,因为这些或多或少都会入侵业务代码,还可能影响性能)。
异步服务的验证:在微服务的架构体系中,为了更好地服务解耦,会引入MQ之类的异步服务组件,同时还能起到削峰填谷的作用。这类组件并不好测试。在制定测试策略时,需要了解MQ的选型,关注组件的消费速度、消息不被错误的消费等问题。
03
以上,就是基于微服务架构下的一些常见测试策略。技术架构会随着业务的复杂度不断的演进,微服务的拆分也不是一蹴而就。所以,在制定测试策略时,也需要做到可演进。
当架构刚开始拆分时,我们可以直接按单体架构的测试策略进行测试;
当微服务数量较多时,我们只需要关注重点微服务的连通性、可用性及数据一致性;
当微服务数量达到非常多时,我们需要引入熔断降级机制,并建设统一的日志管理平台;
当微服务数量多到我们反应不过来时,会有更多的验证手段被构建出来。
04
做个小的总结,对于微服务架构的测试策略,在业务层,我们可以沿用原来的测试策略,不需要做太多的变化。而对于架构本身带来的新特性,我们需要有针对性的对应措施,整体如下图所示。