Jmeter执行流程分析

一、使用 Jmeter GUI 进行测试配置

我们在使用Jmeter做性能测试时,通常需要使用 GUI 来配置脚本,生成 .jmx 文件,然后使用命令来执行。脚本的配置通常需要有以下几个步骤:

测试计划 → 线程组 → 循环控制器 → Java请求 → 结果统计

Jmeter执行流程分析

通过以上配置生成 jmx 文件后,再使用命令行执行,生成结果文件,如:jmeter -n -t testscript\Baidu.jmx -l testresult\01-reslut.jtl

二、运行机制 && 源码分析

Jmeter执行流程分析

  • NewDriver 是 Jmeter 程序的入口类,通过反射调用 JMeter 类的 start() 方法;
  • JMeter 类的 start() 方法根据不同的命令来执行不同的启动方法,startGui() 和 startNonGui();
  • startNonGui() 方法又调用了 runNonGui() 方法来执行脚本
  1. 获取脚本文件,
  2. 配置脚本文件,
  3. 将脚本文件解析成 HashTree,
  4. 实例化一个JMeterEngine来对付脚本,JMeterEngine本质就是一个线程,
  5. 调用runTest方法。
HashTree 是 JMeter 执行测试依赖的数据结构,在执行测试之前进行配置测试数据,HashTree将数据组织到一个递归树结构中,并提供了操作该结构的方法StandardJMeterEngine 执行JMeter 测试 ,直接用于本地 GUI 和非 GUI 调用,或者在服务器模式下运行时由 RemoteJMeterEngineImpl 启动JMeterEngine 接口被运行 JMeter的测试类实现,此接口共8个方法,JMeterEngine本质就是一个线程,JMeter类还有其他重要的职责,比如监听所有的 JMeterEngine ,当接收到 GUI 的 StopTestNow / Shutdown 等命令时候来调用JMeterEngine接口相应的方法。

三、Jmeter扩展实现

从上面的分析我们发现:JMeterEngine 依赖于 HashTree,而 HashTree 是由 jmx 文件解析而来,每一个 JMeter 测试计划都会对应一个 jmx 文件。所以我们只要生成合理的 jmx 文件,就可以通过 JMeterEngine 压测引擎去执行测试任务。但是仔细一想发现,我们通过 Jmeter GUI生成一个 jmx 文件,然后 Jmeter 内部又把 jmx 文件解析成了一个 HashTree,再通过 JMeterEngine 来执行,那我们应该能够直接来创建这个 HashTree,并把这个 HashTree需要的内容添加进去,最后就能通过 JMeterEngine 来执行,这样我们就不必去生成 jmx 文件了,可以全部用代码来实现了,如下:

public class JmxCodeDemo {

  /**
   * 使用GUI的方式,做完各种配置之后, 会生成一个jmx文件
   *
   * 实际上这个Jmx文件在给到jmeter进程去执行时,JMeter类去负责将jmx文件解析成hashTree
   *
   * 这个hashTree的内容就跟我们在GUI中配置的关系是一致的, 各种层次的包裹关系
   *
   * 最终去调StandardJMeterEngine,将配置关系设置进去(jmeterEngine.configure(tree))
   *
   * 最后启动(执行)
   */
  public static void main(String[] args) {

    // 1、启动初始化配置
    URL resourceUrl = getResource("jmeter.properties");
    JMeterUtils.loadJMeterProperties(resourceUrl.getPath());
    JMeterUtils.setLocale(Locale.ENGLISH);

    // 2、创建一个测试计划
    TestPlan testPlan = new TestPlan();
    testPlan.setName("local perf test plan");

    // 3、创建一个javaSampler
    JavaSampler javaSampler = new JavaSampler();
    javaSampler.setName("local perf java sampler");
    javaSampler.setClassname(CaseDemo.class.getName());

    // 4、创建一个循环控制器
    LoopController controller = new LoopController();
    controller.setName("local perf loop controller");
    controller.setLoops(5);
    controller.addTestElement(javaSampler);
    controller.initialize();

    // 5、创建threadGroup
    ThreadGroup threadGroup = new ThreadGroup();
    threadGroup.setName("local perf thread group");
    threadGroup.setNumThreads(3);
    threadGroup.setDelay(100);
    threadGroup.setSamplerController(controller);
    threadGroup.initialize();

    // 6、创建结果收集器
    ResultCollector resultCollector = new ResultCollector();
    resultCollector.setName("local perf result collector");

    // 7、构建同级tree
    HashTree subTree = new HashTree();
    subTree.add(javaSampler);
    subTree.add(controller);
    subTree.add(threadGroup);
    subTree.add(resultCollector);

    // 8、构建层次tree
    HashTree tree = new HashTree();
    tree.add(testPlan,subTree);

    // 9、创建Jmeter引擎并将配置的tree赋值进去
    StandardJMeterEngine jmeterEngine = new StandardJMeterEngine();
    jmeterEngine.configure(tree);

    // 10、执行引擎
    try {
      jmeterEngine.runTest();
    } catch (JMeterEngineException e) {
      e.printStackTrace();
    }
  }
}

后面我们介绍性能测试平台时将会使用这种方式来实现。

相关推荐