JMeter的下载和启动
JMeter是基于Java语言的工具,请确保你在使用JMeter时已经安装了JDK。
下载地址:http://jmeter.apache.org/download_jmeter
Windows GUI启动
安装:解压下载的压缩包,Windows下双击启动apache-jmeter-3.2\apache-jmeter-3.2\bin\ApacheJMeter.jar即可
启动后的界面如下:
Linux命令行启动:
如果在Linux系统启动JMeter,同样将下载的压缩包解压,进入JMeter的bin目录。
执行./jmeter-server &命令即启动了JMeter服务
JMeter基本组件
测试计划(Test Plan):
线程组(Thread Group):
线程组是任何测试计划的起点,所有的逻辑控制器和采样器都必须放在线程组之下。
线程组被用来管理执行性能测试所需的JMeter线程,通过线程组可以:
- 设置线程数量
- 设置线程启动时间及测试持续时间
- 设置执行测试脚本的循环次数
值得一提的是:
- 参数Ramp-Up Period告诉JMeter启动所有线程所需要的时间。该参数不能设定得太短,否则在测试的初始阶段会给服务器过大的压力,也不能设定得太长,否则就会发生第一个线程已经执行完毕,而最后一个线程还没有启动的情况。
- 在调度器控制面板中,可以设定测试运行的启动时间和结束时间,注意设置调度器时需要勾选“循环次数”的“永远”选项。也可以在调度器控制面板中设定“持续时间”和“启动延迟”,注意“启动延迟”会使“启动时间”无效,而“持续时间”会使“结束时间”无效。
采样器(Sampler):
采样器是JMeter向待测服务器发送请求的基础元件。JMeter采样器可以发送HTTP、FTP、JDBC、Java、LDAP、SOAP请求等。下面以http请求为例进行简单说明。
选中线程组,右键->添加->Sampler->HTTP请求
通过HTTP请求采样器,用户可以配置待测接口的域名(或待测服务器的ip)、端口号、http方法、url地址、请求参数等。还可以结合JMeter提供的配置元件管理http请求的header、cookie等内容,这里不做具体说明,如有需要请自行Google。
监听器(Lisener):
监听器提供了对JMeter在测试期间收集到的信息的访问和展现方法。JMeter提供了查看结果树(查看具体的请求和响应信息)、聚合报告(聚合一次压测的请求数、QPS、响应时间、网络吞吐量等信息)、图形结果等多种结果展现方式,可以在日常测试中逐步探索。
同时,监听器还支持将测试结果数据导入,以供后续分析。项目测试的过程中一个常用的使用场景是在Linux环境通过命令行运行测试脚本(下文会讲到),将测试结果记录到文件,测试结束后再windows GUI 模式的监听器中导入测试结果文件进行结果的分析。
注:所有监听器都是保存同样的测试数据,区别在于它们如何展示数据。
定时器(Timer):
默认情况下,JMeter线程在发送请求之间没有间歇,一方面请求过于频繁会对被测服务器造成过大的压力,另一方面无法准确控制请求QPS。所以一般情况下需要通过线程数和定时器配合使用来精确控制QPS。以其中的“Constant Throughput Timer为例进行简单说明:
添加后如下图:
Target throughput(in samples per minute):目标吞吐量。注意这里是每分钟发送的请求数,值应为QPS*60(s)
Calculate Throughput based on,有5个可选项,分别是:
a) This thread only :控制每个线程的吞吐量,选择这种模式时,总的吞吐量为设置的 target Throughput 乘以矣线程的数量。
b) All active threads : 设置的target Throughput 将分配在每个活跃线程上,每个活跃线程在上一次运行结束后等待合理的时间后再次运行。活跃线程指同一时刻同时运行的线程。
c) All active threads in current thread group :设置的target Throughput将分配在当前线程组的每一个活跃线程上,当测试计划中只有一个线程组时,该选项和All active threads选项的效果完全相同。
d) All active threads (shared ):与All active threads 的选项基本相同,唯一的区别是,每个活跃线程都会在所有活跃线程上一次运行结束后等待合理的时间后再次运行。
e) All cative threads in current thread group (shared ):与All active threads in current thread group 基本相同,唯一的区别是,每个活跃线程都会在所有活跃线程的上一次运行结束后等待合理的时间后再次运行。
通过在“线程组”设置的线程数与这里的“Target throughput"进行计算可得出QPS,如配置启动10个thread,控制Target throughput为180(/min),控制方式为This thread only,那么实际发送请求的QPS为:10(线程数)*3(180/min) = 30
断言(Assertion):
用户可以使用断言来检查从服务器获得的响应内容,通过断言可以验证被测服务器返回的响应内容与预期是否相符。有了这个校验才能统计性能测试的错误率指标。
JMeter提供了响应断言、XPath断言、HTML断言等多种断言方式。
需要注意的是,断言会影响作用域内的所有采样器。如果要让断言只影响某个采样器,需要将断言作为采样器的子项。
想要查看断言结果,可以为线程组添加“断言结果”监听器。失败的断言也会在“查看结果数”和“用表格查看结果”两种监听器中显示。另外,在“Summary Report”和“聚合报告”中还会以错误百分率的形式统计
其他组件:
配置元件:配置与案件与采样器紧密关联。虽然配置与案件并不直接发送请求,但它可以添加或者修改请求。
逻辑控制器:控制JMeter的测试逻辑,比如合适发送请求。例:可以添加“交替控制器”来轮流发送多个请求
前置处理器:在采样器发出请求之前做一些特殊操作。
后置处理器:在采样器发出请求之后做一些特殊操作。
篇幅有限,仅就常用的几个组件做了简单介绍,后续如有需要,请自行Google,有好用的组件也欢迎更新到此wiki。另外JMeter还通过添加扩展包来扩展各个组件。更多强大的功能等待发现中……
JMeter脚本的运行
GUI运行
JMeter在GUI模式下支持多种方式来启动测试脚本:
菜单栏:运行->启动
快捷键:Ctrl+R
界面按钮:菜单栏下方的绿色箭头按钮
命令行启动
进入JMeter的bin目录
执行命令:./jmeter -n -t myTestScriptName.jmx -l myTestResultFileName.jtl
其中:-n 即选择非GUI模式运行
-t 指定要运行的脚本文件
-l 指定测试运行数据文件
启动后屏幕上会打印出请求数、测试时间、QPS、响应时间、错误率等概要信息,详细信息可在测试执行完成后从结果文件(.jtl)中获取和分析。
测试的终止
GUI模式
菜单栏:运行->停止
快捷键:Ctrl+.(停止)——如果可能的话,立刻停止所有线程。Ctrl+,(关闭)——要求线程在当前工作完成后停止,不会中断任何采样器的工作。
界面按钮:运行按钮旁边的红色停止按钮
命令行模式:
JMeter 2.3.2版本后,会监听指定端口(默认为4445)上的命令。目前支持的命令包括:Shutdown(关闭)、StopTestNow(停止)。这两天命令可以分别使用bin目录下的shutdown[.cmd|.sh]或者stoptest[.cmd|.sh]脚本来完成。
测试脚本的参数化
用户自定义的变量
开发JMeter性能测试脚本的过程中,可以用变量来代替某些在测试计划中经常出现的表达式,或者某些在单次测试运行过程中不发生变化,但在多次测试运行之间会变化的参数,如:主机名或者线程数量。
为可以在测试计划级别添加全局的“用户定义的变量”,也可以添加“配置元件”->“用户定义的变量”来定义变量(需要注意的是配置元件形式添加的变量需要考虑其作用域),
定义好的变量,在其他地方就可以用“${变量名}“的方式引用了。
从csv文件读取参数
使用JMeter测试的过程中,往往需要在单次运行的脚本中同一接口使用不同的参数来模拟线上真实的情况(如参数化用户名、密码模拟多用户在线,不同的tvid、src等参数模拟很多不同用户的不同播放请求),这个时候我们就可以使用“CSV Data Set Config”来实现。
添加“配置元件”->“CSV Data Set Configs”后的页面及相关的配置如下图
CSV Data Set Config主要配置参数简要说明如下:
- FileName:同目录下的csv文件名(也可以写绝对路径)。注意csv文件直接写数据,不需要参数名。
- File Encoding: csv文件编码,默认为ANSI,可以不填。
- Variable Names:定义csv文件中的参数名,参数之间以逗号分隔。定以后可以在脚本中以“用户定义的变量”相同方式引用。
- Delimeter: 分隔符,默认为逗号。
- Recycle on EOF:是否允许循环取文件中的参数。
- Stop Thread on EOF: 当Recycle on EOF为false并且Stop Thread on EOF为true,则读完csv文件中的记录后,停止运行。
- Sharing Mode: 线程共享方式。
神奇的JMeter函数
命令行运行时的参数传递——利用jmeter属性
常规的命令行运行
./jmeter -n -t myTestScriptName.jmx -l myTestResultFileName.jtl |
若想传入参数,可使用-J参数,作用是覆盖(添加)JMeter中的属性。如:
sh jmeter -n -t /data/APPdata/jmeterscripts/test.jmx -Jcount=1 |
其中count是属性名称,1是属性的值。在运行时,程序会自动覆盖属性count后再执行
注意:当通过JMeter属性的方法调用变量时,需要修改变量的传入方式。普通的定义变量是:${count}的形式。但是本方法是通过添加JMeter的属性,属性和参数是不同的,因此在调用中采用${__P(count)}的形式进行调用。(注意是两个下划线)
关于JMeter的属性,参考http://www.cnblogs.com/puresoul/p/4850060.html
录制测试脚本
JMeter 录制脚本的需求多见于web测试,用户打开一个web页面的过程中,实际需要很多个http请求(页面本身的请求、css、img等等)、还有可能涉及头信息、cookie等的管理,这种情况下可以将JMeter作为代理来使用,在web页面模拟用户真实操作,JMeter自动记录http请求,测试人员可以后续对录制的脚本进行简单修改优化作为测试脚本直接使用。
JMeter Proxy 录制HTTP请求:
在工作台右键添加“非测试元件”->“HTTP代理服务器”
添加后可配置:
端口:代理服务器监听的端口号,默认为8080,也可自行设定。
目标控制器:录制的http采样器放到哪里。这里选择直接放在线程组下面,也可以在线程组添加录制控制器后这里选择“使用录制控制器”
包含模式和排除模式:分别定义了http 代理服务器将采集|排除的url类型。
配置完成后点击“启动”来启动HTTP代理服务器。
代理服务器启动后,将浏览器代理配置到本地(127.0.0.1)刚刚配置的端口上。这样,你在浏览器访问网页的操作就会按照设置好的规则被记录并添加到JMeter脚本里了。
你还可以通过添加“查看结果树“监听器来查看录制的http请求的情况。
录制HTTPS请求
录制HTTPS请求需要为浏览器安装JMeter生成的证书。具体安装和使用方法请参考JMeter官方文档。
另外需要注意的是,录制HTTPS请求的时候需要配置HTTPS的代理,见下图:
分布式运行
JMeter对于CPU和内存的消耗比较大,因此,当需要模拟数以千计的并发用户时,使用单台机器模拟所有的并发用户就有些力不从心,甚至会引起内存溢出错误。为了让JMeter工具提供更大的负载能力,我们可以利用JMeter支持多台机器协同产生负载的机制。通过远程运行JMeter,测试人员可以跨越多台低端计算机复制测试,这样就可以模拟一个比较大的服务器压力,一个JMeter客户端实例,理论上可以控制任意多的远程JMeter实例,并通过他们收集测试数据。
下面以主控机A(Controller),控制B、C、D三台负载机(Agent)为例,简单说明JMeter分布式运行的步骤:
前提条件:ABCD四台机器运行在同一局域网内,且四台机器的JDK版本和JMeter版本一致。
- 启动B、C、D三台服务器的JMeter服务,${jmeter_directory}/bin/jmeter-server &。正常启动会提示“创建远程服务***”
- 同样方式启动A服务器的JMeter服务
- 在A服务器执行${jmeter_directory}/bin/jmeter -n -t testScriptName.jmx -R B服务器ip,C服务器ip,D服务器ip 。其中-R 表示远程启动,后面跟负载机的ip地址,多台负载机用逗号隔开。
- 也可以通过JMeter bin 目录下的配置文件jmeter.properties将负载机器的ip统一写到配置项"remote_hosts"中,这样远程启动JMeter脚本的时候用-r代替-R,不必输入负载机ip地址了。
JMeter最佳实践及其他注意事项
减少JMeter的资源占用
- 使用非GUI模式运行
- 尽量少使用监听器。如果命令行运行时使用-l命令将测试结果保存到jtl文件,脚本运行时可以禁用所有监听器,运行结束后可以手动导入jtl文件查看和分析结果。
- 尽量不要使用大量相似的采样器。可以通过CSV Data Set和同一个采样器的循环来实现不同请求的需要。
- 不要使用太多太复杂的断言
Jmeter常见问题及解决方案
- JMeter发送http请求出现“”Non HTTP response code"错误,有可能是被测服务响应超时,也有可能是JMeter工具本身的问题。JMeter本身问题解决办法参考stackoverflow。具体原因分析的文章http://www.xxdafa.com/article?id=57b33ba7b8063f1a058b457a
- JMeter同一个线程组有大量HTTP采样器(如几百个)时,很容易造成out of memory问题。原因尚未确认,实践确认可以通过将这些http请求分散在多个线程组中可以解决此问题。
参考资料:
《零成本实现Web性能测试——基于Apache JMeter》——温素剑 编著
http://lijingshou.iteye.com/blog/2047613
http://www.ubik-ingenierie.com/blog/jmeter_performance_tuning_tips/
http://jmeter.apache.org/usermanual/index.html