什么是JMeter
Apache JMeter是一个开源的Java桌面软件。设计的目的就是进行C/S架构软件的负载测试。随着发展,有很多人也用来进行一些静态资源或者动态资源的性能测试。可以支持的测试对象有:静态文件,Java Servlets, CGI scripts,Java 对象,数据库,FTP服务器等等。
JMeter的原理就是模拟产生一个大数据压力包,然后使用不同的负载测试方法去研究server,object或者network的健壮性以及分析在过载情况下的性能指标。
当然,对于一些简单的workflow,你也可以使用JMeter来建立一套带断言的脚本来进行复杂度较低的回归测试。
有一点要注意的是,JMeter本身不是一个Browser,一定要理解这一点。
一些技术细节我们就不在这里讨论了,下载后就可以很简单的通过bat文件将其运行起来,至于安装java环境,那就不在详细讨论了。
下面,先来理解一些标准术语,方便我们后面进行讲解。
Test Plan
Test Plan,是用来集合需要执行的步骤的一个节点,基本上所有的操作,都是在Test plan里存在的。在Test plan之外的步骤,不会被执行。
你可以将Test plan理解为一个要实现的测试用例,一个包好了若干测试用例的user story,或者是一个特殊的测试scenario,甚至可以当作一个test suite。完全取决于你在这个Test plan中包含了什么。
包含在Test plan中的节点,我们称之为element。所有的Elements组成了不同结构的Tree存在于Test plan这个root之下。
你可以在其中任意的添加或者删除element或者一个elements tree。
Element
让我们来看看,有哪些element可以被使用。
ThreadGroup
对于每个Test Plan来说,第一个节点永远是ThreadGroup。所有的Controller 元素
和Sampler 元素必须位于ThreadGroup元素中。
ThreadGroup最重要的作用是用来配置一下三个参数:
•Thread的数量
•Thread的ramp-up时间
•执行该Test Plan的次数。
Thread的数量我们很好理解,就是每一个线程模拟一个用户,执行该test plan所有的步骤。数量代表用户模拟数。但是,有一点要注意,从单server上发起的多用户模拟和多server上发起的多用户模拟需要在客户端进行处理。有些server会把单server上所有的请求当作一个用户的请求,而且无法实现多用户并发的模拟。
Ramp-up period是一个需要仔细考虑的设置。它的含义是在指定的period内把所有的Thread创建完毕。例如,有100个Thread,这个period设置为0,那么就是瞬间并发100个Thread。如果设置为2秒,那么就是在两秒内依次把所有的Thread产生。理论上是每隔2/100=0.02秒一个请求。
所以,如果我们在模拟真实的用户请求是,你要有一个预先的response极限,比如0.01秒/response是极限的话,过低的时间频段,只会带来大量无效的请求,更适合over load情况下的性能测试,而不是需要逐级加压的load test的要求。
另外有一个Think Time也值得关注,Think Time是指的思考时间,是一个很明确的时间间隔,Ramp-up period的时间间隔只是理论上的,而Think Time是指定的时间间隔。在模拟多用户并发操作时,我们还要考虑在不同时间节点上的负载平衡。通过将Think Time 和 Ramp-up period相结合,才能更加贴近真实的用户负载场景。
Controllers
JMeter实际上包含了两种Controller元素:Sampler元素和Logic Controller元素。通过二者的组合,从而实现具体的测试内容。
Sampler元素用来定义哪些请求要被发送到server。而且Logic Controller元素则控制那个Sampler元素在什么时候被发送。
Sampler
JMeter现有的Sampler元素有:
•FTP请求
•HTTP请求
•JDBC请求
•Java Object请求
•LDAP请求
•SOAP/XML-RPC请求
•Web Service(SOAP)请求
每个元素里面都有一些相关的属性需要配置来完成请求发送的任务。同时为了更好的控制业务层次,还提供了很多Configure元素来提供给这些Sampler元素进行调用,从而更加完善的控制流程。
同时可以给Sampler元素配置上一个Listener元素用来记录请求返回的结果。当你想对这些返回的结果进行一个验证是,再添加一个Assertion元素即可。
Logic Controllers
对于逻辑控制,那是必不可少的,可以将我们单一的线性步骤列表,变成一个可控制的多层次的复用模块的组合。
提供可以使用的Logic Controller元素有:
•Simple Controller 用于组合sampler和其他logic Controller
•Loop Controller 用于控制loop循环
•Once Only Controller 用于控制仅一次的操作,例如login
•Interleave Controller 交错控制,使得包含的步骤交错执行在每个循环中。
•Random Controller 随机控制,随机选择包含的步骤之一进行执行
•Random Order Controller 随机顺序控制,以随机的顺序执行所有的步骤
•Throughput Controller 执行频度控制,用于控制执行步骤的范围和量。
•Runtime Controller 生命周期控制器,用于控制可生存的时间长度
•If Controller 控制if操作
•While Controller 控制while操作
•Switch Controller 控制switch操作
•ForEach Controller 遍历操作控制,用来便利当前元素的所有可执行场景
•Module Controller 用于控制封装好的Module元素
•Include Controller 用于引入外部的jmx文件,从而控制多个Test Plan组合。
•Transaction Controller 控制如何产生额外的时间测量sampler。
•Recording Controller 控制录制使用的代理服务器的地址
我们会在后面详细的介绍每个controller的具体使用方法。
Test Fragments
该元素是一个特殊的Controller元素,是后来引入的。特点是可以和ThreadGroup处于并列级别的存在于Test Plan的树中。而一般的Controller元素都要位于ThreadGroup的节点之内。
只有当其被Module Controller元素或者Include Controller元素引用后,才会被执行。
Listeners
Listener元素用于提供Jmeter在运行中产生的信息。产生的这些信息,其实就是我们需要的数据报告。也就是我们测试要获得的结果报告。
Listener元素可以产生数据文件报告,图形报告,也可以是直接存储为各种文件格式的报告。
Timers
JMeter在ThreadGroup中产生的Thread都是没有任何停顿的,哪怕是设置了产生间隔,也仍然是连续的去产生Thread,每个Thread之间没有任何停顿。如果你想要在每个Thread间进行停顿,需要设置Timer元素。当然,Timer主要还是用于Sampler去控制产生的压力,从而避免过压的产生,从而得不到有效的数据。
Assertions
当你需要对server返回的数据进行一些分析和判断是,需要使用的就是Assertion元素。这在大压力的情况下很有必要,因为有可能返回速度达到了你的要求,但是很多系统在无法response时,也会返回一条回应。通过Assertion元素,我们才能清楚的知道成功率是多少。
当然,如果你是来构建一套回归测试suites,那么Assertion元素是必不可少的。
Configuration Elements
Configuration element是为Sampler元素服务的。他们不会直接的参与请求的发送过程,但是发送的内容是通过Configuration 元素和Sampler元素的内容组合而成的。该元素只能被同一个父节点的兄弟节点以及子节点所使用,父节点的兄弟节点无法使用。
Pre-Processor Elements
该元素主要是在Sampler元素发送请求之前,进行一些预处理操作使用。
Post-Processor Elements
该元素主要是在Sampler元素发送请求之后,进行一些收尾处理操作使用。最常用的实例就是在获得response的data时候,从data中提取我们想要的特定数据。
Common Execution Order
对于所有element的执行顺序,一般来说是这样的:
Configuration element
Pre-Processor
Timer
Sampler
Post——Porcessor
Assertion
Listener
(我以为listener会在Assertion前面呢)
Properties and Variables
JMeter的properties在文件jmeter.properties中定义。 对于JMeter来说,这是全局共享数据。主要是用来定义一些常用的默认值。在Test Plan中,可以覆盖一些默认的properties。
而JMeter的variables是服务于每个Thread的局部变量。每个Thread使用的variables都是不同的,完全取决它们的自己需要。
而且需要注意的是,Thread在执行的时候是复制了一份variables的副本,修改也是基于副本修改,不会影响被多个Thread共享的原本。
而且variables支持正则表达式。
对于在Test Plan和User Define Variables Configuration Element中定义的variables,是可以被包含在该Test Plan中的所有步骤共享。并且可以使用Set方法去设置新的值,从而使所有的步骤都获得更新。
使用variables最大好处就是可以数据参数化。Variables本身是作为一个储存一个可被共享的常量来设计的。但是,它的本质还是一个可变的数据引用对象。
对于一个循环中,或者多个Test Plan中的一个Test Plan,实际上它等同于一个常量。但是,当多个循环和多个Test Plan存在时,我们要操作的数据对象是相同的,但是数据对象的值可以根据场景进行变化,这就为什么要对将那些最常用的数据对象进行参数化。
举个简单的例子帮助你更好的理解:
比如我们要循环访问一个站点的不同页面, 去查看一个特定的字符串是否存在。那么我们可以将站点地址参数化,从而在不同的站点的Test Plan中使用同一个variable,只需要修改它的值即可。同时,我们在每个page中check的特定字符可以是相同的,也可以根据不同的页面不同。那么将这个特殊字符参数化以后,我们可以用相同的Module来执行所有的重复操作