JMeter 是 apache 开发的基于 java 的压力测试工具。可用于对服务器、网络或对象模拟巨大的负载,来自不同压力类别下测试它们的强度和分析整体性能,另 jmeter 可以使用它做性能的图形分析或在大并发负载测试服务器/脚本/对象。
因为 JMeter 依赖于 JDK 环境,所以需要先安装 JDK, 安装 JDK 的文章很多,网上可以很容易的找到,这里不再赘述。
正常启动之后可以看到如下界面,默认为英文,不过你可以在菜单栏中 【Options】-> 【Choose Language】下选择合适的语言。
为了模拟一下多用户并发测试的情况,需要通过配置线程组来配置所需要的并发信息,在 Test Plan 右击,可以看到 Add,选择添加线程组即可。(Test Plan 是默认的名字,如果你修改了,名称会变)
添加之后如图
**Name:**任意,可以写一个简单易懂的名字
**Comments:**备注信息
Action to be taken after a Sampler error (采样器错误后要采取的措施)
一般常用的为 Contiune 和 Start Next Thread Loop
Thread Properties 中的配置,是我们最关心的,也是这里的配置最重要的部分。
Delay Thread creation until needed: 延时创建线程直到该线程需要采样时。勾选,例如50个线程Ramp-Up Period为10s,那么每隔1s启动50/10=5个线程并运行下面的请求(状态为running);不勾选,测试计划开始后启动所有线程(状态为new),但是不立即执行下面的请求。例如50个线程Ramp-Up Period为10s,那么计划开始后所有线程全部就绪,但第一秒只有5个线程开始运行请求。实际应用中选择哪种都可以,不影响测试结果。
Same user on each iteration: 在 JMeter 中,user 就是线程,此选项的意思是说每个迭代都用相同的线程。在以前 3.x 和 4.x 版本的 JMeter 中,是没有这个选项的。创建好 1 个线程后,每次迭代都是用这个线程,直到测试结束。它的影响就是,比如登录,加了 HTTP Cookie 管理器以后,单个线程多次迭代(注意不是多个线程哦)登录用的都是相同的 Cookie。
5.x 版本加入了这个选项,可以控制每次迭代是否创建新的线程。同时在 HTTP Cookie 管理器也增加了一个选项,控制是否清除旧 Cookie. **默认这个 Same user on each iteration 的选项是勾选的。**因为销毁和创建线程本身就会占用资源,可能会影响性能测试结果。
Specify Thread lifetime
前几天,一个好友问我,为什么我接口响应都是毫秒级的(10ms 以内),但是用 JMeter 进行压测,吞吐量才 30。当时想想,你这接口响应时间肯定超过 100ms 了,不然就算一个线程进行压测 10ms 内响应时间,不会是 30,至少应该 100 呀!
于是她发了测试的结果,然后我和她要了响应的时间图
从测试结果看确实才 30/s,而且 99% 以内的请求都在 7 毫秒就完成,95%的请求在 4 毫秒就完成了。显然根据经验,4 毫秒的响应,一个线程持续压测,也能得到 1(秒)/ 0.004 (秒) = 250 (次/秒),也不可能是 30,于是测试让朋友去优化代码,提高性能。
但单纯的根据响应时间来看,其实并不需要进行优化,于是她发来了测试的线程组配置如下图:
从图中的配置可以看出,线程数为 500,Ramp Up 为 50s, 循环次数为 3,错误操作为继续。
从可以配置可以看出,总请求次数为 500(线程数)* 3(循环次数)= 1500 次,Ramp Up 为 50s, 也就是线程数从 0 到 500 全部投入工作需要 50s(并不是 50s 之前没有线程在工作,是达到 500 个线程同时工作至少需要 50s 开始)
先跳出一下,看看吞吐率的定义:
吞吐率: 单位时间内网络上传输的数据量,也可以指单位时间内处理客户请求数量。它是衡量网络性能的重要指标,通常情况下,吞吐率用“字节数/秒”来衡量,当然,你可以用“请求数/秒”和“页面数/秒”来衡量。其实,不管是一个请求还是一个页面,它的本质都是在网络上传输的数据,那么来表示数据的单位就是字节数。
但是从业务的角度看,吞吐率也可以用“业务数/小时”、“访问人数/小时”、“页面访问量/小时”来衡量。例如,在银行卡审批系统中,可以用“千件/小时”来衡量系统的业务处理能力。
因为在测试 HTTP 请求,这里使用单位时间内处理客户请求数量。从上面的线程组的配置中,假设请求响应的时间忽略不计的情况下(按 0 算),则测试执行的总时间为 50(秒),请求的总次数为 500(线程数)* 3(循环次数)= 1500 次,按照定义的计算方式为 1500(次)/ 50 (秒) = 30(次/秒),也就是说就算测试一个 0 纳秒的接口,得出的吞吐率也是 30(只能小于等于 30)。
通过这个实际例子,可以看出,不合理的线程组配置,会导致不合理的结果。
在测试中,一般都需要进行长时间的压测才能得到一个比较准确的结果,一般在压测时,我是这样进行配置的。
Ramp Up 设置 10,既模拟用户 10s 内可以就绪
Loop Count 勾选 Infinite
Duration 设置 180s,如果测试时间充裕,可以设置 600s,也就是 10 分钟
线程数 分别使用 50、100、150、200、250、300、350、400 进行多轮测试,通过多轮测试来得出应用在不同情况下的表现(当然这样测试时间会长一点,但是效果会好一点)