1.7 性能测试
1.7.1 性能测试的目的
性能测试的目的是验证软件系统是否能够实现用户提出的性能指标,同时发现软件系统中存在的性能瓶颈,进而优化软件。性能测试的目的有评估系统极限并发的能力、判断系统是否有内存溢出与高可用失效等相关现象,以及在长时间高压下性能测试服务器因“疲劳”所产生的其他现象。
1.7.2 性能测试着重观察的指标
Web性能测试需着重观察的聚合报告结果参数如表1-1所示。
表1-1
1.7.3 性能测试存在的误区
在性能测试开始之前,应当着重考虑服务器的硬件配置。各厂商通常表述自己的数据库可以达到多少TPS,但很少说明自己服务器的硬件配置是怎样的。实际上,计算机的硬件配置会极大地影响TPS结果,因此厂商推荐的数据库和程序服务只能作为参考。在进入生产环境之前,应当通过JMeter或基准测试对数据库进行相应的测试。
除硬件配置外,在性能测试准备期间还应着重注意当前带宽是否能够满足性能测试的需要,以免性能测试只返回带宽上限的请求数目,而无法测试出应用程序的极限。在带宽不足的情况下,测试结果是无效的,需视为因带宽不足而导致的结果不正确。
如果部分性能测试结果的错误率过高,则此次性能测试结果应当作废,需视为因错误率过高而导致的结果不正确。因为一旦出现异常与错误,则接口响应时间将是一个无法确定的值,即有些延时太高的线程无法返回,导致整体承载量下降。通常当遇到错误率过高的程序时,应当先进行优化,再重新进行性能测试。
性能测试的平均返回时间应仅作为参考,在生产环境中,95百分位表示大多数正常用户的响应时间,99百分位可视为部分较卡用户的响应时间。不要以平均值作为普通用户的响应时间。
性能测试的最大返回时间通常被视作服务器的TimeOut时间,若该时间过长,则需要对程序进行优化,在限制TimeOut时间后再进行测试,否则性能测试结果的参考性不高。线程在没有被服务器返回的情况下,十分消耗服务器的CPU与内存。与此同时,若中位数或90百分位的用户响应时间过长,则应当对应用程序进行优化。例如,对于HTTP接口来说,5秒以上即算过长的响应时间。若是高并发应用程序,则响应时间应当更少。
如果性能测试的最小时间为毫秒级,那么该数据通常是作为缓存存在的。如果性能测试的平均时间接近最小值,则该测试结果需要作废,因为这很可能是服务器直接对数据进行了返回,并没有真正地进入代码与业务逻辑。此处需要根据系统的特性进行斟酌。
在性能测试中,通常有压力机与被测试机两种类型的机器。由于性能测试工具与脚本同样消耗性能,因此在实际工作中,可能出现多台压力机同时压测一台被测试机的情况,此时需要注意压力机自身的CPU与内存不要处于“爆表”的状态,否则该测试结果应当作废,需视为因压力机无法正常运行而导致的结果不正确。
1.7.4 性能测试应涵盖的内容
下面以登录场景为例,通常性能测试应至少包含以下测试报告:
• 在模拟生产环境的同时,95百分位的用户的登录响应时间是否小于N秒,N为服务方提供的值。例如,单次登录时间超过N秒则将视为系统高并发能力不足,需查看服务器配置及代码,以免由于登录时间过长而影响用户体验。诸如此类验证响应时间的接口,都需要按照百分位的方式进行判断,即绝大部分用户的体验是否正常。另外,对响应时间需要有一个预期,即某系统达到什么样的响应时间则视为合格。因为系统的复杂度和使用场景不同,所以预期也不同。一般来说,单个用户的登录时间不应超过2秒;打开App时,App初始化时间不应超过3秒;页面跳转时间不应超过1秒;跳转下一页的时间不应超过0.5秒;在搜索相关数据时,结果返回时间不应超过0.5秒。
• 在高并发场景下,用户登录是否请求了过多的接口。例如,在登录之后,需要请求N个接口才能展示整体页面,如果是在高并发情况下,则用户体验将会很差。如果在用户登录时或用户登录后需要请求过多的接口,则需要进行优化。例如,对于一个页面可以分别读取数据并部分展示,而不是在全部数据读取完之后才打开页面;在渲染页面时是否有额外的资源消耗;在返回数据时是否有无用字段,是否可对接口进行精简、缓存等。
• 用户登录时是否包含监控的功能,并且在高并发场景下监控仍然能够正常响应,包括用户行为监控、性能监控和服务端硬件监控等。
• 在性能测试时需要进行高并发下的慢连接、慢读取、慢请求等安全测试,以保证在任何情况下都不会因客户端的性能问题而影响服务器的性能。例如,某用户使用App通过WebSocket协议连接Java服务器,在Java服务器主动推送数据后,由于App网络较差无法正常收到数据,而使Java服务器内存溢出导致崩溃。此时需要使用JMeter+Fiddler组合测试,即弱网下的高并发测试。
• 长时间大量用户连续登录和退出是否会引发内存溢出、缓存失效或穿透缓存等问题。
• 连续使用虚假用户进行登录,是否被有效拦截,是否会穿透缓存。