在众多测试工作中,性能测试似乎是最难上手的。性能测试报告的易读性也最差,所以在每次做性能测试的进度更新和结论陈述时,我都会先用几分钟的时间给听众先讲一讲测试方法和重点指标的含义。否则讲到测试细节时,会不断被各种科普类提问打断。
在这里将性能测试的诸多细节做个回顾,着重从侧能测试报告的角度入手。
Scripts 脚本
性能测试用脚本描述用户行为。由于性能测试针对的是目标的承载能力,性能测试脚本会与常见的功能测试自动化脚本稍有不同。最直观的差别在于,性能测试脚本的易读性比较低,与用户操作行为不能一一对应。
如果测试对象为网站或页面,其脚本描述的是向服务器端发起的各式请求。请求本身相互独立,不一定存在先后顺序,也不一定全部并发。发送重复的请求也是合理的,这视前端的设计而定。
如果对web services端进行性能测试,脚本则是各式api requests的集群。
Scenarios 场景
性能测试需要构造特殊的测试场景,以达到设定的压力。经常用到的手段有如下几种:
V-user 虚拟用户。通过构造并发用户数量,增加或减少性能压力。
start / end v-users 加载和释放虚拟用户数量。通常我们会设置成百上千个并发用户,那么1k并发用户同时开始执行测试脚本,还是逐步进入测试队列,会对性能测试结果造成很大不同。为了得到稳定的性能测试结果,我们通常会分批加载v-users,并在结束前分批释放。例如设置20分钟内进入500个并发用户,保持2小时后,再用20分钟将并发用户逐步从500降低至0。有效的测试结果只采纳其间的2小时数据。
Think time 思考时间。模拟用户在每次操作之间会停顿多长时间。真实情况下,人在浏览页面或进行操作时,并定会有或长或短的停留时间。这个数值在同一脚本里可以设置同一取值,例如对网页性能测试时,设置平均think time为3秒。可想而知,think time越小,访问速度越快,设置的性能压力也就越大。反之亦然。
Duration 测试时长。即使在恒定的访问压力下,服务端的表现也会随时间长短而不同。如果希望验证服务端是否存在内测泄漏等问题,则更需要设置相当长的duration。很多时候,项目经理企图以测试轮数或测试完成时间作为项目进度的依据,也就是否不合理了。
Cache 缓存是性能测试世界中的第一捣蛋鬼。如果平均响应时间极短,请首先考虑是否绕过了所有缓存。由于缓存机制复杂,开发团队不一定会事无巨细地提前解释清楚,就需要性能测试团队保持怀疑,甄别清楚。当然,对开发架构了然于心是进行测试策略设计和执行,分析结果时的最大底气。
说回缓存的问题。要绕过缓存,有两个思路。第一,有针对性的关闭缓存。第二,设计超出缓存的测试数据,例如每个并发用户有各自独立的登陆授权;脚本中同一request的参数各不相同。
7. Rendezvous 集合策略。单纯设置v-users数量,会达到完美的并发效果吗?就像集结了千军万马过桥,答案是否定的。如果不做额外设置,测试执行的过程可能变为所有用户同时操作脚本中的用例1,有的1秒钟结束便开始执行用例2。有的虚拟用户等待5秒钟才完成用例1,再开始执行用例2;并依次进行下去。也就是说除了用例1,剩余的用例都没有达到预定的并发压力。
设置集合点和集合策略,就是为了达到更极限的测试效果。例如在每个用例前,插入一个“集合点”,测试执行时,就可以将用户请求停下来,知道用户数量达到满足条件,比如要求90%的虚拟用户都到达集合点。那么,我们可以更有保障地将让用户同时发出每一个请求。
服务端的主要监控指标
老板通常只想听到一个答案,测试的结论是通过还是不通过?支撑这个结论的确实众多指标综合考量的。
1. Errors 错误信息 常规的性能测试工具都能一定程度实时搜集错误信息。更可靠的方式是依托专业的服务监控工具,例如new Relic, Splunk, Zabbix, 或开放的application log和DB log. 在几小时的性能测试中,完全没有错误是不可能的。只要错误率在合理范围之内,测试就值得进行下去。另一方面,也要关注错误种类,如果规律地出现404,可能由于使用了不合理的测试数据造成的。如果在某个时间段大量出现502、501等,就值得进一步做troubleshooting。
2. 90% response time 90分位服务端响应时间。首先,性能测试搜集的是服务端响应时间,而不是客户端响应时间。当产品经理问,为什么客户说每次登录要2、3分钟,你们给的测试报告里的响应时间只有3秒时,请耐心地回答以下内容。客户端发起请求后,除了等待服务端端响应,还需要在处理数据、渲染元素等,才会最终将整个页面呈现在用户面前。处理数据包、渲染元素受到浏览器自身机制、电脑配置、网络传输延时等因素等影响。因此,服务端响应时间会短于实际客户的感知时间。
其次,服务端响应时间是系统对每个请求进行处理并返回结果的完整过程计时。从web server到app sever的网络传输,数据库读取的消耗等都会包括在内。传统性能测试不会解析每个步骤分别需要的时长,需要搭配profile更精确地分析。
第三,每轮测试中,每个请求会被访问多次,因此最终呈现的响应时间是个统计学上的概念。个人认为,90分位数比平均响应时间更加客观。而每个页面的访问时间,是页面中所有请求的集合。我们会取请求消耗最长的时间表示页面的响应时间。
3. QPS 每秒钟处理完请求的次数。QPS是衡量吞吐量的重要指标,具体指发出请求到服务器处理完成功返回结果。
QPS = 并发量 / 平均响应时间
QPS直观地量化了服务器的处理能力。在设计性能测试脚本之处,我们可以根据生产环境的实际吞吐量,有目标地设定QPS。在恒定的测试环境中,每轮测试的QPS应保持平稳。也就解释了另一个常见的问题,测试结果中的QPS是越大越好吗?-不一定。如果没有架构上的调整,QPS应该在一定水平范围中保持稳定。而当系统达到最大承载能力,qps就上不去了。此时如果继续增加压力,会发现QPS下降。这通常标志着我们找到了系统瓶颈,系统超负荷工作,内存等其他消耗导致系统性能下降。
4. Throughput 吞吐率。与QPS结合来看的是吞吐率,单位为byte per second。因而可知,吞吐率是单位时间内网络上传输的数据量,也可以指单位时间内处理客户请求的数量。本质上,吞吐率是数据量或者说字节数的统计,与QPS的计量并不相同。有趣的事情都发生在QPS和Throughput的不同走向上。
性能测试的种类
1. benchmark run 没有预期目标的测试都是瞎折腾。在恒定测试环境下建立基线,是性能测试历程的原点。建立基线或主标尺,可以用较低的压力执行测试脚本,搜集服务端的运行数据作为基础参考。
2. load test 负载测试是最常见的性能测试种类之一。负载测试中,不断对系统施压并持续一段时间,预期目标为得到服务端的性能指标的安全临界值。
3. duration test 稳定性测试的目标是验证系统长期高负荷时,是否也能满足正常业务需求。因此duration test通常会持续8-12个小时,以期发现内存泄露等问题。节选生产环境上的真实流量做traffic replay是更有说服力的duration test。
4. stress test 压力测试的目标非常直接,通过有针对性的增大压力,找到系统或某组件的承载临界值,或者验证系统在峰值负载下的表现是否符合预期。
5. spike test 通过不断调整并发量,验证是否会存在功能缺陷,例如数据读取回收机制是否正常等。
还有诸如容灾测试、容量测试等不同的性能测试种类。这些概念并不是为了存在而存在,而是为了实实在在的目标去设计和实施。再强调一次,确定预期目标,再适时选择合理的策略并不断调整和优化,才是真正有效的测试!