java - 停止从 Java 代码开始的 JMeter 非 GUI 测试

标签 java jmeter

我从 Java 代码启动了 JMeter JMX 测试:

StandardJMeterEngine jmeter = new StandardJMeterEngine();
..
jmeter.configure(testPlanTree);
jmeter.run();

我希望能够停止测试(从测试外部,例如命令行),类似于使用(从 cmd)从非 GUI 模式运行的选项:

jmeter -n -t MyTest.jmx

停止:

shutdown.cmd (/sh)
stoptest.cmd (/sh)

当从非 gui cmd 启动时,我可以看到它等待信号:

Waiting for possible shutdown message on port 4445

如果从我的非 GUI Java 代码启动,它不会监听此端口。如何将此功能添加到此模式?

任何建议将不胜感激? 谢谢!

最佳答案

我建议调查JMeter.java源代码,特别是以下方法:

private static void waitForSignals(final List<JMeterEngine> engines, DatagramSocket socket) 

它包含实现所需功能所需的一切。

为了以防万一,这里是一个示例代码 list ,只需用您自己的路径替换 JMeter 和测试脚本文件的路径即可:

import org.apache.jmeter.engine.JMeterEngine;
import org.apache.jmeter.engine.StandardJMeterEngine;
import org.apache.jmeter.save.SaveService;
import org.apache.jmeter.util.JMeterUtils;
import org.apache.jorphan.collections.HashTree;
import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.HeapDumper;
import org.apache.log.Logger;

import java.io.File;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;


public class JMeterFromExistingJMX {

    private static final Logger log = LoggingManager.getLoggerForClass();

    public static void main(String[] argv) throws Exception {
        // JMeter Engine
        final StandardJMeterEngine jmeter = new StandardJMeterEngine();

        // Initialize Properties, logging, locale, etc.
        JMeterUtils.loadJMeterProperties("/opt/jmeter/bin/jmeter.properties");
        JMeterUtils.setJMeterHome("/opt/jmeter");
        JMeterUtils.initLogging();// you can comment this line out to see extra log messages of i.e. DEBUG level
        JMeterUtils.initLocale();

        // Initialize JMeter SaveService
        SaveService.loadProperties();

        HashTree testPlanTree = SaveService.loadTree(new File("/opt/jmeter/bin/test.jmx"));

        final List<JMeterEngine> engines = new ArrayList<>();
        engines.add(jmeter);

        int port = JMeterUtils.getPropDefault("jmeterengine.nongui.port", 4445); // $NON-NLS-1$
        int maxPort = JMeterUtils.getPropDefault("jmeterengine.nongui.maxport", 4455); // $NON-NLS-1$
        if (port > 1000) {
            final DatagramSocket socket = getSocket(port, maxPort);
            if (socket != null) {
                Thread waiter = new Thread("UDP Listener") {
                    @Override
                    public void run() {
                        waitForSignals(engines, socket);
                    }
                };
                waiter.setDaemon(true);
                waiter.start();
            } else {
                System.out.println("Failed to create UDP port");
            }
        }

        // Run JMeter Test
        jmeter.configure(testPlanTree);
        jmeter.run();
    }

    private static void waitForSignals(final List<JMeterEngine> engines, DatagramSocket socket) {
        byte[] buf = new byte[80];
        System.out.println("Waiting for possible Shutdown/StopTestNow/Heapdump message on port " + socket.getLocalPort());
        DatagramPacket request = new DatagramPacket(buf, buf.length);
        try {
            while (true) {
                socket.receive(request);
                InetAddress address = request.getAddress();
                // Only accept commands from the local host
                if (address.isLoopbackAddress()) {
                    String command = new String(request.getData(), request.getOffset(), request.getLength(), "ASCII");
                    System.out.println("Command: " + command + " received from " + address);
                    log.info("Command: " + command + " received from " + address);
                    switch (command) {
                        case "StopTestNow":
                            for (JMeterEngine engine : engines) {
                                engine.stopTest(true);
                            }
                            break;
                        case "Shutdown":
                            for (JMeterEngine engine : engines) {
                                engine.stopTest(false);
                            }
                            break;
                        case "HeapDump":
                            HeapDumper.dumpHeap();
                            break;
                        default:
                            System.out.println("Command: " + command + " not recognised ");
                            break;
                    }
                }
            }
        } catch (Exception e) {
            log.error("Error", e);
        } finally {
            socket.close();
        }
    }

    private static DatagramSocket getSocket(int udpPort, int udpPortMax) {
        DatagramSocket socket = null;
        int i = udpPort;
        while (i <= udpPortMax) {
            try {
                socket = new DatagramSocket(i);
                break;
            } catch (SocketException e) {
                i++;
            }
        }

        return socket;
    }
}

查看Five Ways To Launch a JMeter Test without Using the JMeter GUI了解更多信息和示例

关于java - 停止从 Java 代码开始的 JMeter 非 GUI 测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39226085/

相关文章:

java - 检查 boolean 值时,我不断收到空指针异常错误

java - Java 迭代器或增强循环是否按创建顺序保证结果?

java - 使用 Jmeter 进行 Cassandra 测试

使用 'java' 编译类时,Java 11 不会生成 .class 文件

java - 在 Eclipse e4 中禁用表查看器中的行

java - 在忽略字段的列表中查找重复项

java - JSR223 PreProcessor ScriptException : groovy. lang.MissingPropertyException:jmeter 中没有此类属性

http - JMeter:如何发送带有内容类型 header 的请求?

proxy - 设置 JMeter 代理以记录本地 Web 应用程序上的事件

jmeter - 为什么通过验证日志与服务器时间相比,Jmeter 响应时间不准确