性能工具之JMeter5.0核心类JMeterEngine源码分析

简介: 【5月更文挑战第17天】性能工具之JMeter5.0核心类JMeterEngine源码分析

概述

JMeterEngine 接口被运行 Jmeter 的测试类实现,此接口共 8 个方法。
API地址:https://jmeter.apache.org/api/org/apache/jmeter/engine/JMeterEngine.html

逻辑关系

image.png

简要解读:

  • HashTree是依赖的数据结构;
  • SearchByClass 用来查找 HashTree 中的所有节点,并把节点实例化为真正的对象,例如图中TestPlan/ThreadGroup/JavaSampler/ResultCollector 在 HashTree 中本来都是只是配置,全部通过 SearchByClass 实例化的;
  • 实例化出来的对象如果是 TestStateListener 类型,则会在有生命周期的函数回调,测试前调 testStarted,结束掉 testEnded, 比如 ResultCollector是该类型的一种,在结束的时候回调 testEnded 方法完成 report 的写入;
  • PreCompiler 用来解析 Arguments, 把 TestPlan 节点中配置的参数作为JMeterVariables 加入到测试线程上线文中;
  • ThreadGroup 用来用来管理一组线程,包括线程的个数/启动/关闭等;
  • StopTest 作为其内部类对外不可见,作为一个 Runnable,作用是异步停止测试,stopTest方法也是通过该内部类实现的。

    工程位置

    image.png

主要方法

  • void configure(HashTree testPlan);
  • void exit();
  • boolean isActive();
  • void reset();
  • void runTest() ;
  • void setProperties(java.util.Properties p);
  • stopTest();
  • void stopTest(boolean now);

void configure(HashTree testPlan)

配置引擎,HashTree 是 JMeter 执行测试依赖的数据结构,configure 在执行测试之前进行配置测试数据。可以参考接口JMeterEngine的实现类
StandardJMeterEngine

    @Override
    public void configure(HashTree testTree) {
   
   
        // Is testplan serialised?
        SearchByClass<TestPlan> testPlan = new SearchByClass<>(TestPlan.class);
        testTree.traverse(testPlan);
        Object[] plan = testPlan.getSearchResults().toArray();
        if (plan.length == 0) {
   
   
            throw new IllegalStateException("Could not find the TestPlan class!");
        }
        TestPlan tp = (TestPlan) plan[0];
        serialized = tp.isSerialized();
        tearDownOnShutdown = tp.isTearDownOnShutdown();
        active = true;
        test = testTree;
    }

从 HashTree中 解析出 TestPlan , 获取 TestPlan 的 serialized 和tearDownOnShutdown 并保存为 local 属性,同时把整个 HashTree 也保存到 local。

  /** Thread Groups run sequentially */
    private volatile boolean serialized = false;

    /** tearDown Thread Groups run after shutdown of main threads */
    private volatile boolean tearDownOnShutdown = false;

StandardJMeterEngine 依赖线程组 ThreadGroup, 一个测试中可能会有多个线程组,如果 serialized 为 true,则 StandardJMeterEngine 会串行的去执行这些线程组,每启动一个 ThreadGroup 主线程都会等它结束;否则就并行执行所有的线程组。
tearDownOnShutdown 与 PostThreadGroup 配合使用的,这个 Special Thread Group 专门用来做清理工作

/**
 * PostThreadGroup is a special type of ThreadGroup that can be used for
 * performing actions at the end of a test for cleanup and such.
 */
public class PostThreadGroup extends ThreadGroup {
   
   
    private static final long serialVersionUID = 240L;
}

如果在 HashTree 配置中有 PostThreadGroup,那么在主线程组(ThreadGroup)跑完之后,StandardJMeterEngine 会去检查这个tearDownOnShutdown 属性,若该属性值 true 就启动PostThreadGroup。

void exit()

是为 Remote Test 准备的,如果当前的测试是从一个客户端的 JMeter 执行远程 JMeterEngine 的 remote samples,则应该调用该 exit() 方法来关闭远程的测试。
远程退出由 RemoteJMeterEngineImpl.rexit() 和notifyTestListenersOfEnd() 调用 iff exitAfterTest 为 true; 反过来,run( ) 方法调用,也调用 StopTest 类

/** 
     * Remote exit
     * Called by RemoteJMeterEngineImpl.rexit()
     * and by notifyTestListenersOfEnd() iff exitAfterTest is true;
     * in turn that is called by the run() method and the StopTest class
     * also called
     *
     */
    @Override
    public void exit() {
   
   
        ClientJMeterEngine.tidyRMI(log); // This should be enough to allow server to exit.
        if (REMOTE_SYSTEM_EXIT) {
   
    // default is false
            log.warn("About to run System.exit(0) on {}", host);
            // Needs to be run in a separate thread to allow RMI call to return OK
            Thread t = new Thread() {
   
   
                @Override
                public void run() {
   
   
                    pause(1000); // Allow RMI to complete
                    log.info("Bye from {}", host);
                    System.out.println("Bye from "+host); // NOSONAR Intentional
                    System.exit(0); // NOSONAR Intentional
                }
            };
            t.start();
        }
    }

boolean isActive()

isActive 在测试中 JMeterEngine 返回值:
boolean 用于显示引擎是否处于活动状态的标志(在测试运行时为true)。在测试结束时设置为 false

public boolean isActive() {
   
   
    return active;
}

void reset()

重置。在 StandardJMeterEngine 中就是直接调用 stopTest(true)

  @Override
    public void reset() {
   
   
        if (running) {
   
   
            stopTest();
        }
    }

void runTest()

调用该方法用来执行测试。参考 StandardJMeterEngine 的实现,启动一个线程并触发它的run()方法,若报异常则调用stopTest(),抛出 JMeterEngineException。

  @Override
    public void runTest() throws JMeterEngineException {
   
   
        if (host != null){
   
   
            long now=System.currentTimeMillis();
            System.out.println("Starting the test on host " + host + " @ "+new Date(now)+" ("+now+")"); // NOSONAR Intentional
        }
        try {
   
   
            Thread runningThread = new Thread(this, "StandardJMeterEngine");
            // 启动一个线程并触发它的run()方法
            runningThread.start();
        } catch (Exception err) {
   
   
            stopTest();
            throw new JMeterEngineException(err);
        }
    }

void setProperties(java.util.Properties p)

设置属性,可以将额外的配置文件通过该方法添加进去。它会保存在JMeterUtils 中,该类保存了JMeterEngine runtime 所需要的所有配置参数。

public void setProperties(Properties p) {
   
   
    log.info("Applying properties " + p);
    JMeterUtils.getJMeterProperties().putAll(p);
}

stopTest()

立即停止执行测试

public synchronized void stopTest() {
   
   
    stopTest(true);
}

void stopTest(boolean now)

停止测试,若 now 为 true 则停止动作立即执行;
若为 false 则停止动作缓刑,它会等待当前正在执行的测试至少执行完一个 iteration

@Override
    public synchronized void stopTest(boolean now) {
   
   
        Thread stopThread = new Thread(new StopTest(now));
        stopThread.start();
    }

private class StopTest implements Runnable{
   
   ……}

小结

执行引擎(JMeterEngine),本质是一个线程,JMeterEngine 接口被运行 JMeter的测试类实现。

参考资料:

目录
相关文章
|
3月前
|
测试技术 数据库 UED
Python 性能测试进阶之路:JMeter 与 Locust 的强强联合,解锁性能极限
【9月更文挑战第9天】在数字化时代,确保软件系统在高并发场景下的稳定性至关重要。Python 为此提供了丰富的性能测试工具,如 JMeter 和 Locust。JMeter 可模拟复杂请求场景,而 Locust 则能更灵活地模拟真实用户行为。结合两者优势,可全面评估系统性能并优化瓶颈。例如,在电商网站促销期间,通过 JMeter 模拟大量登录请求并用 Locust 模拟用户浏览和购物行为,可有效识别并解决性能问题,从而提升系统稳定性和用户体验。这种组合为性能测试开辟了新道路,助力应对复杂挑战。
123 2
|
2月前
|
测试技术 持续交付 Apache
性能怪兽来袭!Python+JMeter+Locust,让你的应用性能飙升🦖
【10月更文挑战第10天】随着互联网应用规模的不断扩大,性能测试变得至关重要。本文将探讨如何利用Python结合Apache JMeter和Locust,构建高效且可定制的性能测试框架。通过介绍JMeter和Locust的使用方法及Python的集成技巧,帮助应用在高负载下保持稳定运行。
76 2
|
3月前
|
缓存 Java 测试技术
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
使用JMeter对项目各个接口进行压力测试,并对前端进行动静分离优化,优化三级分类查询接口的性能
118 10
谷粒商城笔记+踩坑(11)——性能压测和调优,JMeter压力测试+jvisualvm监控性能+资源动静分离+修改堆内存
|
2月前
|
测试技术 持续交付 Apache
性能怪兽来袭!Python+JMeter+Locust,让你的应用性能飙升🦖
【10月更文挑战第2天】随着互联网应用规模的不断膨胀,性能测试变得至关重要。本文将介绍如何利用Python结合Apache JMeter和Locust构建高效且可定制的性能测试框架。Apache JMeter是一款广泛使用的开源负载测试工具,适合测试静态和动态资源;Locust则基于Python,通过编写简单的脚本模拟HTTP请求,更适合复杂的测试场景。
73 3
|
4月前
|
存储 Linux 数据库
性能工具之JMeter + Grafana + InfluxDB 性能平台搭建
【8月更文挑战第7天】性能工具之JMeter + Grafana + InfluxDB 性能平台搭建
83 1
性能工具之JMeter + Grafana + InfluxDB 性能平台搭建
|
4月前
|
监控 Java 测试技术
实战派必看!Python性能测试中,JMeter与Locust如何助力性能调优
【8月更文挑战第6天】性能优化是软件开发的关键。本文介绍JMeter与Locust两款流行性能测试工具,演示如何用于Python应用的性能调优。JMeter可模拟大量用户并发访问,支持多种协议;Locust用Python编写,易于定制用户行为并模拟高并发。根据场景选择合适工具,确保应用在高负载下的稳定运行。
144 4
|
4月前
|
测试技术 数据库 UED
Python 性能测试进阶之路:JMeter 与 Locust 的强强联合,解锁性能极限
【8月更文挑战第6天】在数字化时代,确保软件在高并发下的稳定性至关重要。Python 提供了强大的性能测试工具,如 JMeter 和 Locust。JMeter 可配置复杂请求场景,而 Locust 则以 Python 脚本灵活模拟真实用户行为。两者结合,可全面评估系统性能。例如,对电商网站进行测试时,JMeter 模拟登录请求,Locust 定义浏览和购物行为,共同揭示系统瓶颈并指导优化,从而保证稳定高效的用户体验。
110 1
|
2月前
|
测试技术 持续交付 Apache
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
【10月更文挑战第1天】Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
164 3
|
1月前
|
测试技术 持续交付 Apache
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
Python性能测试新风尚:JMeter遇上Locust,性能分析不再难🧐
73 3
|
1月前
|
缓存 测试技术 Apache
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
告别卡顿!Python性能测试实战教程,JMeter&Locust带你秒懂性能优化💡
55 1