探索性测试固然重要,但仅有探索,如果测试人员本身不了解系统的一些内部逻辑的话,会出现两种情况:第一种是只验证设计好的场景,其他一些异常的情况,自己无法解释,但本身又不是验证标准,导致很多隐藏的问题终在线上爆发;第二种像一个无头苍蝇,漫无目的地进行探索,浪费了时间,却达不到好的效果。在飞天测试中,我们要求测试人员必须从方案设计之初甚至是讨论需求时和开发的同学在一起讨论,测试的同学需要比开发更加理解系统的设计原则。

  了解分布式系统的工作原理后,测试同学会明白如何去做一个有效的灰盒测试。比如,在某个关键点加请求压力会事半功倍;在哪个时机去做测试结果断言会更方便、彻底或完整;甚至知道对一个模块进程如何注入代码,模拟重现机率很小的协议通信丢包的问题。

  有一个很典型的例子。早期,我们内部开发一个基于表结构的存储引擎时,曾出现过这样一件事情:测试程序在终验证一致性时,一直都是通过的,但业务方和我们一起做E2E测试时,会有很低的概率发现数据读出来是错误的。测试人员百思不得其解,后发现,这份数据在写入的时候,会先在三个地方进行修改,但由于一些时序和锁的问题,在改过了两个地方之后返回成功了,第三个地方是在内存中,过一阵子会被重新刷成正确的值。如果当时测试的同学知道系统里面的这些设计,当时会设计写入过程中,对数据一致性进行实时检测,不会在代价更高的E2E测试中发现问题,解决的效率也会因此而提高。

  带压力和随机故障模拟的长时间稳定性测试

  文首提到大规模生产集群上的问题,很难在小规模的测试集群上发现。究其原因,主要是两方面导致的。

  ● 大规模集群中原本小概率的单机故障会随机器数增加,导致集群整体的硬件故障率线性提升,甚至多种故障同时发生的概率也大大增加。

  ● 机器数增多会导致对飞天模块的压力点发生转移。以弹性计算(ECS)为例,在300台变600台时发现,原本担心的文件系统Master还未成为QPS瓶颈,负责锁文件协同的命名服务首先成为瓶颈。

  此外,各种故障的组合爆炸也让完整的容错测试在设计和执行上的代价变得太大。

  为解决上述困难,在飞天测试实践中,我们逐渐积累出一套带背景压力和随机故障模拟的长时间稳定性测试方案。背景压力主要是针对各个底层模块的读写压力,通常会针对某类应用场景来模拟。

  基于分而治之和系统仿真的方法,我们实现了一些轻量级的压力工具,让各模块的Master机器和Slave机器分别接受到大规模生产集群上的类似访问压力和连接规模。另外,还增加一些诸如CPU、Memory、Network的资源消耗器,以模拟生产环境业务繁忙导致机器资源紧张的场景。

  故障模拟上,一方面,尽可能丰富软件手段模拟软硬件故障,比如磁盘错误(包括坏盘、只读等)、机器宕机、重启、断网、交换机重启、主要模块进程重启、假死等;另一方面,这些故障模拟操作都会按照预先设定比例进行随机组合。在这样的背景压力和随机故障操作下,长时间(至少7×24小时)持续运行上层应用模拟程序/作业,同时通过在线监控系统来检查飞天是否正常。

  简而言之,我们用背景压力解决压力点问题,用长时间跑解决小集群的故障小概率问题,用随机故障模拟和组合来解决容错测试设计和执行的代价问题。

  实践证明,飞天很多重要的Bug都是通过这个测试被发现的。当然,这类测试也有短处,是问题调查需要较长的时间,要求测试人员对系统有较深的了解和诊断能力。

  结束语

  大规模分布式系统的测试是一项非常有挑战的工作。尽管我们持续落实各层测试,积累实践经验,创新测试方法,但由于测试条件的限制、生产环境的复杂,软件问题仍然无法完全依赖测试消除。本文仅仅提到了飞天测试在Test in Lab方向的一些思考和实践,完善的飞天质量保证体系其实需要Test in Lab和Test in Production双管齐下,这才是飞天测试乐此不疲的努力方向。