为什么选择使用JMeter

当被问到这个问题的时候,也许你会在脑海里产生很多的理由,比如:

  • Apache基金会下的开源项目,没有版权问题;
  • 为数不多的还在持续更新的开源性能自动化测试工具;
  • 支持协议丰富,是商用测试工具最佳替代品;
  • 有专门的插件项目做支撑,使得你在实践中有更多的选择,比如http://jmeter-plugins.org/就提供了很多优秀的插件为你在使用JMeter执行测试时,可以选择更多的组件来制定测试计划,完成测试过程,监控测试数据。

而我的回答是:

关键在于不要简单地把JMeter理解为一个单纯的性能测试工具,而应该意识到它还是一个优秀的框架,这甚至成为我选择它的一个最根本理由,在这里所有的组件都可以通过自由编写插件的方式进行添加和完善,对于一个测试工程师来说为JMeter编写插件式组件其乐无穷!

JMeter基本组件类型及实现方法

对于JMeter的基本组件,我们可以将其简单的划分为两大类:

  • 一类是具备GUI的组件,即可以通过JMeter图形管理控制器在测试计划Tree中进行添加的组件,主要包括ThreadGroup(线程组)、Config(配置元件)、Timer(定时器)、Modifier(前置处理器)、Extractor(后置处理器)、Controller(逻辑控制器)、Sampler(测试抽样器)、Assertion(断言)和Listener(监听器);
  • 另一类是非GUI组件,这类组件典型的代表是Function(函数)和某些子测试抽样器,如JavaSamplerClient。

对于组件一般有两种实现方法:

  1. GUI与逻辑控制分离:GUI部分通过继承各种组件GUI抽象类,逻辑控制部分通过继承组件逻辑抽象类和实现各种接口方式从而实现不同组件的内部逻辑控制;
  2. GUI与逻辑控制不分离:与分离方法的区别在于不单独实现GUI部分,在逻辑控制部分通过实现TestBean接口方法从而实现对GUI界面的配置。

JMeter插件式组件实现细节概述

TestElement是所有组件的最基本单元,组件类都是TestElement类的子类,JMeter定义了上一章节所介绍的几种组件模型,并对其规范了各自所需发挥的作用。

(1)GUI部分的实现 
GUI部分的实现我们可以在JMeter实现主类org.apache.jmeter.JMeter中发现端倪,该类实际实现了JMeterPlugin接口中的getIconMappings()方法来映射组件所对应的GUI图标,并为映射关系定义了一个二维数组,如下代码:

private static final String[][] DEFAULT_ICONS = {
{ "org.apache.jmeter.control.gui.TestPlanGui", "org/apache/jmeter/images/beaker.gif" },
{ "org.apache.jmeter.timers.gui.AbstractTimerGui", "org/apache/jmeter/images/timer.gif" },
{ "org.apache.jmeter.threads.gui.ThreadGroupGui", "org/apache/jmeter/images/thread.gif" },
{ "org.apache.jmeter.visualizers.gui.AbstractListenerGui", "org/apache/jmeter/images/meter.png" },
{ "org.apache.jmeter.config.gui.AbstractConfigGui", "org/apache/jmeter/images/testtubes.png" },
{ "org.apache.jmeter.processor.gui.AbstractPreProcessorGui", "org/apache/jmeter/images/leafnode.gif"},
{ "org.apache.jmeter.processor.gui.AbstractPostProcessorGui", "org/apache/jmeter/images/leafnodeflip.gif"},
{ "org.apache.jmeter.control.gui.AbstractControllerGui", "org/apache/jmeter/images/knob.gif" },
{ "org.apache.jmeter.control.gui.WorkBenchGui", "org/apache/jmeter/images/clipboard.gif" },
{ "org.apache.jmeter.samplers.gui.AbstractSamplerGui", "org/apache/jmeter/images/pipet.png" },
{ "org.apache.jmeter.assertions.gui.AbstractAssertionGui", "org/apache/jmeter/images/question.gif"}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

可以看到只要是插件类的GUI部分继承了以上数组中的GUI类,JMeter框架便会自动将其映射为所对应的组件类型和图标。

(2)逻辑控制部分的实现细节,我们根据组件类别进行一一介绍:

ThreadGroup(线程组)组件

ThreadGroup(线程组)组件继承AbstractThreadGroup抽象类,通过重写各类控制方法,如void scheduleThread(JMeterThread thread) 、stopThread(String threadName, boolean now) 、threadFinished(JMeterThread thread)等,来达到控制和协调各线程(虚拟用户)的行为,线程组是构建一个性能测试模型的最基本组件。


Config(配置元件)组件

Config(配置元件)组件相对其他组件比较特殊,通过继承ConfigTestElement类或只需要GUI部分的实现即可完成本体任务,而对于一个需要配置的组件类则需要实现ConfigMergabilityIndicator接口的public boolean applies(ConfigTestElement configElement)方法,用来指明哪些Config组件可以用来对其进行配置,这里参考TCPSampler的源代码如下:

private static final Set<String> APPLIABLE_CONFIG_CLASSES = new HashSet<String>(
Arrays.asList(new String[]{
"org.apache.jmeter.config.gui.LoginConfigGui",
"org.apache.jmeter.protocol.tcp.config.gui.TCPConfigGui",
"org.apache.jmeter.config.gui.SimpleConfigGui"})); @Override
public boolean applies(ConfigTestElement configElement) {
String guiClass = configElement.getProperty(TestElement.GUI_CLASS).getStringValue();
return APPLIABLE_CONFIG_CLASSES.contains(guiClass);
}

以上代码指明LoginConfigGui、SimpleConfigGui和TCPConfigGui这三个配置元件可以对TCPSampler组件进行配置。


Timer(定时器)组件

Timer(定时器)组件通过继承AbstractTestElement抽象类,实现Timer接口的delay()方法来实现对时间的控制,主要的控制内容如下:

  • 控制线程延时,即用来模仿思考时间(ThinkTime)或键盘时间(KeyTime);
  • 控制线程行为,如SyncTimer(同步计时器),就是内部利用CyclicBarrier来控制阻塞和释放全部运行线程的逻辑行为,从而达到“集合点”的目的。

Modifier(前置处理器)组件

Modifier(前置处理器)组件通过继承AbstractTestElement抽象类,实现PreProcessor接口的process ()方法控制逻辑,常常需要对线程上下文中的当前Sampler和前一个SampleResult进行识别和判断,以做出正确的处理,一般的行为是通过取出SampleResult的某些值或直接在当前Sampler启动sample方法之前对其某些属性进行修饰。


Extractor(后置处理器)组件

Extractor(后置处理器)组件通过继承AbstractTestElement抽象类,实现PostProcessor接口的process ()方法控制逻辑,常常需要对线程上下文中的前一个SampleResult进行识别和判断,以做出正确的处理。


Controller(控制器)组件

Controller(控制器)组件通过继承GenericController类,通过重写Sampler next()、void setDone(boolean done)、int getIterCount()、void reInitialize()等方法来控制Sampler的测试行为。


Sampler(测试抽样器)组件

Sampler(测试抽样器)组件继承AbstractSampler抽象类,通过重写SampleResult sample(Entry e)方法,实现测试过程以及测试结果的采集功能。


Assertion(断言)组件

Assertion(断言)组件通过继承AbstractTestElement抽象类,实现Assertion接口的getResult(SampleResult result)方法对结果内容进行判断,从而实现断言方法,用于对Sampler组件所产生的抽样采集结果内容进行断言。


Listener(监听器)主要有两种方案:

  • 直接继承AbstractTestElement,实现sampleListener或Visualizer等接口方法
  • 实现ResultCollector和Runnable等接口方法

我们可以从实际用途上将其分为两大类Report (报告)和Vizualizers(监视器)。 
Report (报告)继承AbstractListenerElement抽象类,通过实现sampleOccurred(SampleEvent e)方法,对所有采集事件中所产生的SampleResult进行处理,从而生成报告; 
Vizualizers(监视器)主要用于特定的监控任务,比如监控系统资源利用率的组件,与Report的区别在于Vizualizers必须继承一个 ResultCollector类,并在收集器中通过开启额外线程方式完成自定义的数据采集。


上面还介绍了诸如Function(函数)这一类非GUI组件,这类组件的实现比较简单,而且功能比较单一,只需要继承相应的抽象类。

(3)一些TestElement需要实现的主要接口说明

为了实现更多的特性,组件在必要时还需要实现一些主要的接口和方法,下面举例说明:

NoThreadClone接口: 
This class is not cloned per thread, so this is shared,可以理解为一旦实现了NoThreadClone接口,这个TestElement便不会在线程组下的每个线程中创建,而是一个全局化的组件,因此,无法使用getThreadContext()方法。反之,我们可以发现JMeter实际是通过TestElement的clone()方法为线程组下的每个线程拷贝创建属于各自的线程上下文内的TestElement,A new instance is created for each thread group, and the clone() method is then called to create copies for each thread in a thread group.如果想要对某些共享资源进行同步操作,需要参考如下方法:

private transient Object lock = new Object();//锁对象不需要进行序列化,因为分布式在不同主机内存中的锁对象不必保持一致
@Override
public Object clone() {
Clazz clazz = (Clazz) super.clone();
clazz.lock = lock; //保证所有克隆对象共享同一个锁对象
return clazz;
}

注:这是种显式的共享对象方法,由于Java在克隆类对象时,默认是一种“浅克隆”方式,因此,不显式的共享上述锁对象,该锁对象也是默认共享的。

LoopIterationListener接口: 
将通过实现 iterationStart(LoopIterationEvent event)方法,控制对每次发生迭代事件时所需要实现的逻辑。

Serializable接口: 
为了实现在分布式测试模型中保持一些配置和对象的一致性,就需要实现Serializable接口,通过序列化方式保持不同主机对象属性的一致性。

TestStateListener接口: 
将通过实现testStarted(String string)和testEnded(String string)方法,控制对测试状态变化事件时所需要实现的逻辑。

另外,在实际插件的编写过程中还会包括如Remoteable、Interruptible、ThreadListener等接口的应用,会在后面的具体章节进行详细介绍和应用。

组件即插件,只需一步插入JMeter框架

将编写好的插件式组件插入JMeter框架非常简单,只需要将组件整体打包为jar包,并将其拷贝到$JMETER_HOME/ lib/ext路径下即可使用!

Apache Jemeter 开发插件的更多相关文章

  1. 如何为Apache JMeter开发插件(二)—第一个JMeter插件

    文章内容转载于:http://lib.csdn.net/article/softwaretest/25700,并且加上个人一些截图 本篇将开启为JMeter开发插件之旅,我们选择以Function(函 ...

  2. 如何为Apache JMeter开发插件(一)

    本文转载于http://blog.csdn.net/column/details/12925.html,作者:xreztento 作者写的很精华,我打算在此系列操作一遍后,加多点截图,便于更多人更快上 ...

  3. eclipse SE增加Web开发插件

    最近接触了些java项目,之前安装了eclipse SE版本.没有Web开发插件,调试不了Web代码.点击“Window”--“Preference” 左边菜单栏是找不到“Server”项来配置服务器 ...

  4. Visual Studio 2012 Ultimate 上安装 Python 开发插件 PTVS

    1.我的环境 操作系统:32位 Win7 旗舰版 Service Pack 1 VS版本:Microsoft Visual Studio Ultimate 2012 版本 11.0.50727.1 R ...

  5. 通过Nutch扩展点开发插件(添加自定义索引字段到solr)

    爬虫系统:通过Nutch扩展点开发插件(添加自定义索引字段到solr) 准备工作 爬虫环境 -- nutch2.3.1 + solr4.10.3 + hbase0.98 开发环境 -- Eclipse ...

  6. JMeter开发插件——图片验证码识别

    我们在性能测试中总会时不时地遭遇到来自于应用系统的各种阻碍,图片验证码就是一类最常见的束缚,登录或交易时需要按照图片中的内容输入正确的验证信息后,数据才可以提交成功,这使得许多性能测试工具只能望而却步 ...

  7. [原创] 毕设---在myeclipes中安装Hadoop开发插件

    1.安装Hadoop开发插件 hadoop安装包contrib/目录下有个插件hadoop-0.20.2-eclipse-plugin.jar,拷贝到myeclipse根目录下/dropins目录下. ...

  8. Apache Cordova开发环境搭建(二)VS Code

    原文:Apache Cordova开发环境搭建(二)VS Code 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u011127019/articl ...

  9. Apache Cordova开发环境搭建(一)-Visual Studio

    原文:Apache Cordova开发环境搭建(一)-Visual Studio 一.使用Visual Studio开发Apache Cordova手机App 1.版本要求,Visual Studio ...

随机推荐

  1. XML修改节点值

    基于DOM4J 先获取根节点 doc.getRootElement() 然后获取需要修改的节点 doc.getRootElement().node(int) 重新赋值 doc.getRootEleme ...

  2. Git建立独立分支

    前言 在码云建立git项目后默认分支是master, 这里如果直接在码云新建分支, 会指定默认分支; 所以通过git 命令git checkout --orphan 新分支名 创建独立分支 创建 创建 ...

  3. 实习小结(二)--- SSM框架搭建

    SSM项目框架搭建 前几天做了一个学生信息管理的项目,使用纯控制台输入,查询数据库,将信息在控制台中打印,功能完善得差不多之后,老师让将这个项目移植到Web中,使用Spring+SpringMVC+M ...

  4. ES6学习笔记(二)-字符串的扩展

    一.字符的 Unicode 表示法 JavaScript 允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点. 表示法只限于码点在\u0000~\uFFFF之间的字符, ...

  5. JavaWeb学习总结(五):HttpServletRespone对象(一)

    Web服务器收到客户端的http请求,会针对每一次请求,分别创建一个用于代表请求的request对象.和代表响应的response对象.request和response对象即然代表请求和响应,那我们要 ...

  6. JavaScript访问对象的属性和方法

    对象的属性和方法统称为对象的成员. 访问对象的属性 在JavaScript中,可以使用“ . ”和“ [ ] ”来访问对象的属性. 二者区别:“ . ”表示法一般作为静态对象使用时来存取属性.而“[ ...

  7. 03.CSS动画-->自定义动画

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. WinForm实现Rabbitmq官网6个案例-RPC

    获取源码 客户端代码: namespace RabbitMQDemo { public partial class RPC : Form { private readonly static RPC _ ...

  9. OpenCV获取与设置像素点的值的几个方法

    Title: OpenCV OpenCV像素值的获取与设置 Fn 1 : 使用 Mat 中对矩阵元素的地址定位的知识 (参考博文:OpenCV中对Mat里面depth,dims,channels,st ...

  10. AndroidStudio中logcat不输出信息

    2017年11月27日,记住这个日子.今天第一次感觉到被批评了,由于自己技术知识储备不足导致今天的外出工作等于浪费时间.正式因为这个logcat不输出信息的问题,前几回不输出信息了我就从新启动了开发工 ...