何为过载异常测试
  过载,简单地讲是系统当前所承受的压力超过了自身的处理能力。异常,是指一切非正常的运行状态。回顾诸多项目事故不难发现,当大压力遇上异常,所引发的往往都是触目惊心的血案。
  2012年6月29日,供电故障影响了AWS US East Region中约7%的EC2和EBS实例,在电力恢复后的集中恢复过程中,EC2和EBS管理服务过载,同时大量服务器上线触发ELB管理服务的一个未知BUG,并进而导致ELB管理服务过载,整个恢复过程持续数小时。
  2014年1月,某应用由于推广活动,特定接口调用量指数级增长,其依赖的后端服务缓存超时,触发大量回调,应用服务器和后端服务器双方互调接口全部超时,连接占满,系统不可用时间接近1小时。
  如何有效减少惨案的发生,需要我们提前对某些过载和异常进行模拟测试,我们所说的过载异常测试是指当系统处于大压力背景下,通过一些手段使系统运行在异常状态时所进行的测试。过载异常测试属于异常测试,也许有人觉得重新搞个名字有点哗众取宠,但其实只是想突显压力在异常测试中的重要性。其所关注的是在持续压力下,系统中某个异常状态的累积效应和连锁反应。如果没有压力或者压力较小,异常状态有可能被消化而没有积累到某个临界点。
  对系统的预期
  在测试之前,需要事先对测试过程中可能出现的系统行为有所预期:
  异常出现后的应用及系统行为,在超出系统处理能力后能否合理拒绝后续的请求,能否继续提供服务,正常情况下系统应该正常处理请求,而不是挂住卡死。
  异常消除后的应用及系统行为,系统能否在短时间内从异常状态中恢复过来。
  整个过程中需要观察各项资源的变化,尤其是连接和句柄是否会出现泄漏等
  只有确定了预期行为,后续的测试和分析才会有据可依。
  如何模拟压力
  大压力是过载异常测试的一个前提,压力好不是单一的,应该尽量模拟线上的请求模式或者采用真实流量数据,因为系统中的逻辑单元往往存在相互依赖的关系,某些连锁反应需要复杂的逻辑路径来覆盖和触发。脱离线上实际情况的过载异常测试好像空中楼阁,其借鉴意义会大打折扣。那么,有什么方法模拟线上压力呢?这里可以采用线下模拟和线上引流两种方式产生我们需要的流量。
  线下模拟需要对生产环境的请求数据进行分析,抽取出一个近似的模型,包括各种请求类型的比例、并发数、数据传输或流量大小、数据库数据构成和规模等等。其实这项任务本身是一个大的课题,模型越真实测试效果当然越好。
  线上引流则推荐tcpcopy工具,它免去了建立模型的过程,直接实时从线上复制请求,而且对生产环境影响小,但并不是所有线上请求都能在测试环境落地,可能存在一些数据准备和请求适配的问题,总之无法保证所有请求都能在测试环境得到正确响应。两种方式各有优劣,可以根据项目自身情况选择。
  如何模拟异常
  接下来我们可以开始模拟异常了,主要从以下几个方面考虑。
  资源超限
  这里的资源是指广义上的资源,可以是应用服务层面,也可以是操作系统层面:
  应用服务层面的资源主要包括线程池、连接池、有界队列等,这类资源通常是由配置项进行设置的,一般能够通过有限的并发达到其上限;
  操作系统层面的资源主要是CPU、磁盘和内存,可以通过一些工具模拟资源争用,例如使用FIO和Cpulimit等工具可模拟磁盘和CPU资源的争用。
  响应变慢
  说到响应一般涉及到多个子系统的同步调用或者说依赖。假设在一个简单的系统中,A调用B,B调用C和D,我们需要覆盖所有使响应变慢的路径。而对于路径上特定节点的响应变慢,如上例中B变慢的情况,又可以分解为B接收A的请求变慢和B返回A的响应变慢两种。
  响应变慢主要通过tc和iptables两个工具来模拟,tc主要用于流量限制模拟,iptable用于实现限制连接的建立。
  依赖服务的错误或异常
  如果所依赖的后端服务因为某种原因出现大量错误或异常,如http请求返回大量5xx响应、rpc调用抛出大量异常等,我们需要关注这些异常是否都能正确处理,需要检查资源有没有回收、连接能不能释放或者关闭,会不会出现内存和连接泄漏。
  这种情况可以通过mock服务模拟,在mock服务中设置一个随机数使其有一定概率返回给被测应用错误或异常。如果确实存在某种资源泄漏,运行一段时间后我们的请求将完全失败。