在过去的工作经历中,没有自己使用压测工具对接口进行压测的经验,但由于目前所在的部门除了开发以外,就剩几个算不上产品的"产品",测试人员更不存在了。而且目前的需求比较复杂,前端页面会定时请求接口刷新数据,接口压力较大,因此需要对本次需求开发的接口进行压力测试,对接口性能做出一个评估。
本次使用的测试工具为 JMeter,由于是对 web api 进行压测,因此主要使用的是 Http Request Sampler,可以通过 File -> Templates -> Building a Web Test Plan
来创建模板,也可以直接右键 Add Threads 然后右键 Thread Group -> Add -> Samplers -> Http Request
,这样我们就能得到一个测试用例主体了。
如果有多个接口需要测试,可以创建 Http Request Defaults(右键 Thread Group -> Add -> Config Element -> Http Request Defaults)
,指定域名、请求前缀、公共参数等,然后在 Http Request 中指定详细请求地址以及参数。
在 JMeter 中,参数可以脚本化,可以很方便地构建不同的测试用例,避免请求同一个接口导致压测效果不准确。Tools -> Function Helper Dialog
可以打开函数帮助窗口,里面包含 JMeter 支持的所有函数,而常用的应该就是随机数了,${__Random(0,1,)}
这个函数代表着随机生成一个从 0 到 1 之间的整数。其他函数可参照官方文档进行了解。
构建完 Http 请求用例之后,就可以来设置压测的量级了,打开 Thrad Group 标签页,修改 Number of Threads
和 Ramp-up period
两个参数,前者顾名思义就是线程数量,在真实场景中对应于用户量,后者代表这些线程需要在多长时间内启动完毕。比如 10000 --- 30
代表着 30s 内需要启动 10000 个线程。若没有设置第二个参数,则会立即创建所有线程,当线程数量较大时,很有可能会直接将服务压垮,比如 IIS 最长队列 1000,而线程数 10000,此时大概率 API 接口会直接返回 503。
以上步骤已经将请求准备好了,接下来需要添加结果展示模块。右键 Thread Group -> Add -> Listener -> View Results Tree
View Results Tree 可以展示所有的请求详情。右键 Thread Group -> Add -> Listener -> Summary Report
Summary Report 可以展示压测的整体效果。
完成以上步骤,基本就可以开始进行测试了,而在测试过程中,有几项因素可能会严重影响到测试结果:
- 压测机器端口数量
- 接口响应数据大小
- 压测机器带宽
当压测线程数较大时,可能会超出压测机器允许创建的端口上限,此时会有大量的请求失败,这个问题网上有解决方案,可自行搜索。
接口响应数据大小以及压测机器带宽可以归类为同一场景,就是带宽打满了,导致吞吐量上不去。这种情况本人的解决方案是,先将压测机器放在接口宿主机上,虽然这样会导致二者相互影响(最主要的体现是 JMeter 会抢占大部分 CPU),从而影响到测试结果,但是在接口响应数据较大的情况下,带宽的影响远远大于 CPU 的影响;其次,先将接口的响应数据简化,测试程序运行效率,但是这样明显无法达到真实的测试效果,但可以先测试程序逻辑是否正常、高效。
经过以上测试验证程序效率基本没问题之后,再改回正常的响应数据进行测试,通过观察测试结果来决定接口优化策略,对于接口优化,本次需求个人主要采用以下两种方式:
- 加缓存,个人用了两种缓存策略:
- 常驻缓存,即永远不会过期的缓存数据,数据的更新主要由后台定时任务来处理。此处还有部分特殊数据,因为访问频率较高,因此还将原始数据的多份衍生数据也做了缓存,比如将一个列表数据,按照不同字段排序生成正序、逆序数据
- 二级缓存,二级缓存的使用需要注意的是缓存过期时间应该比上级缓存更短,以此保证数据的更新频率能得到一定的保证
- 数据压缩,此处还分了两种不同的处理
- 在 API 接口处使用 GZip 压缩,主要是针对接口数据量较大的情况,不要对所有接口都进行压缩,因为可能压缩成本会比数据传输成本更高
- 直接在缓存服务器中存入压缩数据,这样也能减小缓存服务器的内存压力,同时加快缓存存取效率。这种方式最好使用在可以返回给前端的数据,比如热点数据,数据从缓存服务器中取出之后,直接返回给前端,需要注意的是,如果数据是以字符串存取的方式,还需要转换成字节数组的方式,前端才能够识别。此外需要在 Response Header 中增加 Content-Encoding: gzip 的标识。