移动测试开发 JMeter+BlazeMeter+Metersphere 压力测试踩坑实践
在进行性能测试之前,我们需要了解需要模拟的场景,影响性能的因素、软硬件环境。
根据最近一次的压力测试,把测试过程中遇到的问题以及测试过程进行总结。
测试需求
需要模拟用户登录操作进行测试,登录成功之后,提取浏览器 session,进行第三方应用跳转动作。整个流程需要 3-4 个接口才能完成,一次完整的动作流程需要共享 session。
需要达到的效果:数据库中存有 200 万的数据量,不同用户并发登录 + 应用跳转 TPS>5000。
测试准备
1.脚本录制
测试之前需要进行脚本录制,研究了几种浏览器录制脚本的工具最终选择了 chrome 插件 BlazeMeter 进行脚本录制。相比于 BalazeMeter,BadBoy 工具近几年没有更新,只支持 IE 浏览器。而 Jmeter 自带的代理方式录制脚本,需要使用火狐浏览器设置 jmeter 代理,使用也不方便,设置代理后录制脚本过程中会影响服务器自身插件、脚本校验等功能,在录制过程中往往会遇到一些问题导致服务访问报错,而且录制的脚本还需要修改过滤才能提取出真正需要压测的脚本。BalazeMeter 可以录制浏览器的操作,直接提取 jmeter 脚本,通过域名筛选,提取出有效的脚本:
通过登录之后,应用跳转,在 BalazeMeter 中查看保存的脚本 dev.*.360.cn 域名的三个脚本为登录、初始化、获取应用列表的脚本。其他为跳转到华为应用的脚本。
通过 BalazeMeter 导出 Jmx 文件,可以过滤域名(dev.*.360.cn 识别成了 undefined,这个没有关系,只要能识别就可以)由于压测对第三方应用会造成很大压力,因此之后调整了测试方案,即只提取自己服务器相关的接口就可以了。选择 undefined.undefined 域名,保存 jmx 文件,至此,测试脚本就生成了。
Jmeter 打开脚本可以看到设置的用户代理:
2.数据构造
导入 jmeter 脚本,在 BalazeMeter 录制的脚本中,直接使用已经配置好 cookie 管理
Same user on each iteration 默认为勾选状态,相同用户共用 session,请求不会返回 session 信息。
要模拟多用户并发,需要构造大量的数据,jmeter 在升级以后可以通过配置关闭 Same user on each iteration 共享,一个用户参数设置多并发就可以模拟多个用户。
为了更真实,我在数据库中通过脚本调用先添加了 2000 个用户,通过 csv 文件导入 jmeter,反复调用线程模拟不同的用户。
3.测试优化过程
服务器依赖 redis 和 mysql,服务器性能配置、数据锁、登录密码验证机制也是影响压力的主要因素,需要一个持续的测试、调优过程才能达到最终的效果。
刚开始调试脚本,使用单机版 Jmeter GUI 模式进行测试,为了方便实时观察持续加压接口请求响应时间、响应结果的变化。
漫长的测试优化过程就开始了。
第一次脚本调试,先设置较小的线程,设置 1000 个线程并发,手动循环执行线程,执行几次之后发现吞吐量(qps)<400,执行几次之后,错误率持续上升:
这对 Qps>5000 的要求差的太远,起初怀疑客户端资源不够导致的 QPS 上不去,找了多台客户端,使用 GUI 以及非 GUI 方式测试脚本,发现运行一段时间后,出现大量的 502 等错误。因此排除了客户端的问题。
通过服务端查看 CPU,发现 8 核 16G 服务器 15 个 pod cpu、数据库 CPU 在压力请求时瞬间打满。
从服务器 CPU、内存参数来看,理论上不应该这么小的压力瞬间就出问题。
后来经过研发分析代码,发现代码中的数据库、redis 锁以及密码验证机制会影响性能,为了进一步确定问题,搭建了同样的环境,重新编写了单纯的访问接口,进行压力测试,发现单纯的接口访问,在单 pod 环境下进行压力测试 qps 能达到 1.5 万以上:
经过分析,还是代码逻辑影响性能很大。
又经过代码调整,对登录接口进行优化,分别对优化前的 login 接口和优化后的 loginR 接口进行单 pod 压力测试,做性能对比:
发现 loginR QPs 单 pod>1000,而 login 接口 QPS<200。性能还是有很大差别。
之后优化接口后,同时扩大副本数量进行压力测试,单客户端的 jmeter 也不能满足 QPS>5000 的性能压测,之后采用 metersphere 进行压测,线程并发最大设置为 10000,用四个压力节点进行测试
发现 qps 不是按照指定目标成倍提升的,持续一段时间后,错误率明显提升。
观察 redis 发现,redis 分布中,有很多响应超时的现象,redis 内存占用率很高:
之后调整 redis,扩大集群方式,调整 redis 读取锁时间、内存释放配置等重新进行测试。经过不断的调整,最终 qps 达到>6000 的效果。
4.后续
数据库数据增至 200 万,发现登录接口 qps>9000qps,与之前的测试结果不符:
经服务端分析,没有读取到数据库,修改后发现数据量为 200 万时,qps 与小数据量差别不大仍为>6000qps。
之后又做了读写并发压力测试,写入测试的时候,为了避免数据冲突,通过 beanshell 前置脚本生成不同的用户,保证每次执行都是插入新的用户修改后压力测试读写并发>6000qps。
总结
压力测试过程中影响性能的因素很多,并发线程的数量,数据量大小,redis、mysql 数据库配置、程序处理逻辑、内存、CPU 配置等都会对压力有影响,需要针对不同场景进行测试、对比,发现影响性能的因素,通过不同的并发场景观察 CPU、数据库、redis 压力,响应时间的变化,找到程序执行的痛点,达到提升性能的效果。测试过程中也要观察服务端线程是否按照预期正常执行,防止遗漏处理逻辑导致测试数据不准确。