测试环境:
- 测试客户端:腾讯云 Ubuntu 16.04.1(2 核、8G), Jmeter CLI 4.0
- 被测服务端:腾讯云 CentOS 7(4 核、16G), Java 服务接口 +MySQL DB
测试之前:
- 不要用 Jmeter 的 GUI 模式进行压力测试 (官网没有做明确的说明为什么, 只是说为了得到一个更加精确地结果,猜测 Jmeter 的 UI 刷新等会增加统计时间);
- 随着线程数的增加,Jmeter 会占用越来越多的内存,一旦不够用,Jmeter 可能会假死甚至直接退出,所以你需要在允许的范围内,尽量改大 Jmeter 运行时的堆内存 (修改方式,进入 jmeter 的 bin 目录,vi jmeter,然后修改下图所示的地方为红圈所示,这里设置为 4G,根据你自己的客户端做配置)
- 单核 2~3GHZ 的 CPU 可以启动 1000~2000 个线程,如果要增大单体客户端的请求发起能力,需要增加 CPU 质量或数量,参考这里
开始测试
压力测试情况分两种,一种是有定量需求的,一种是没有定量需求的。定量需求,就是给了你明确的压力测试参数,并且要求服务器的达到相应的指标;另一种就是不给你任何输入,要求你测出一个现有的架构的瓶颈。我们就属于后一种,因为没有明确的指标,我们只能一点点增大压力,看服务器能不能处理得过来 (CPU 怎么样,内存怎么样),以及考虑请求的响应时间 (一般 HTTP 请求的响应时间不要超过 5~10 秒)。
- 背景 服务器关键的接口有两个,一个是注册,一个是登陆,都做了基本的数据格式/数据重复性校验,密码加密等;注册还涉及到写入 DB,而登陆则只有查询 (取 token,校验合法性等).
- 先上 500. 以注册为例,注册的时候需要传一些固定参数及关键参数,比如用户名/密码等,所以,Jmeter 需要一个配置文件,用于随机按行读取注册数据,然后以此发送请求到服务端.右键 TestPlan 新建一个 Thread Group,在这个 Thread Group 下 Add 一个 Config Element:CSV Data Set Config. 这个就是你的账号密码配置文件,此外,还有一种方式,就是使用 Jmeter 的内置语法来完成登录凭证的数据,那个需要对 Jmeter 的内置语法有所了解,这里就不做过多介绍,因为有学习成本,有兴趣的可以看这里.
- 配置测试数据集
1、Filename: 配置文件全路径;2、Variable Names: 变量名称 (与文件中的每一行对应,后面会用到,可以自定义);3、Delimeter: 分隔符 (默认为逗号),其他不常用的不再赘述,相近的阐述在这里
- 配置请求
在 Thread Group 下面 Add 一个 Sampler: HTTP Request,示例如下:
1、Protocol:协议类型 (HTTP/HTTPS); 2、Server Name or IP: 域名或者 IP 地址 (不需要再加 HTTP(s));3、Port Number: 端口号 (如果 Server Name or IP 已经填了域名,而非 IP 地址,则可以省略);4、Method:请求类型 (POST/GET/PUT/DELTE...); 5、Path: 不包含域名前缀在内的 url 地址;6、Parameters/Body/Files Upload 根据自己请求的具体情况添加.
- 结果收集
调试时,右键 Thread Group 添加一个 View Result Tree,可以看到此次请求的结果返回。但是注意,正式运行压测时,千万要去掉这个插件,因为它会影响你的结果统计数据的准确性。
- 运行
保存你的测试计划 (以.jmx 结尾),配置好你的压力并发数据 (Thread Group 里配置,在多少秒内起多少个并发用户,循环控制等),然后执行命令:
apache-jmeter-4.0/bin/jmeter -n -t your_test_plan.jmx -l out_put_result_path.jtl
,执行完成之后,Jmeter 会生成.jtl 的报告文件. 然后你再用 Jmeter 的 GUI 版来查看报告即可.
Jmeter 的缺陷
使用 Jmeter 时,发现一个很有意思的现象:我们的应用后台做了单位时间内同一个 IP 注册用户数量的限制,但是,用 Jmeter 压测,始终跑不出来 BUG(认为这个后台功能已经完美实现了),然后我用 Python 的 aiohttp 和 asyncio,写了一段脚本来压测,一下就暴露了问题,每次跑完总会超出这个数量限制 (说明后台功能存在 BUG),脚本源码看这里。