Hyiki's 技术博客 Back-end Dev Engineer

JMeter源码解析

2023-04-16

  1. JMeter::start 解析命令行参数,决定怎么启动JMeter,这里使用免UI的方式

    public void start(String[] args) {
        // ...
        startNonGui(testFile, jtlFile, remoteTest, reportAtEndOpt != null);
    }
    
  2. JMeter::startNonGui new一个driver实例执行

    private void startNonGui(String testFile, String logFile, CLOption remoteStart, boolean generateReportDashboard)
                throws IllegalUserActionException, ConfigurationException {
        // ...
        if (remoteStart != null) {
            remoteHostsString = remoteStart.getArgument();
            // remote 默认是本地
            if (remoteHostsString == null) {
                remoteHostsString = JMeterUtils.getPropDefault(
                    "remote_hosts", //$NON-NLS-1$
                    "127.0.0.1");//NOSONAR $NON-NLS-1$
            }
        }
        // ...
        driver.runNonGui(testFile, logFile, remoteStart != null, remoteHostsString, generateReportDashboard);
    }
    
  3. JMeter::runNonGui run test in batch mode

    @SuppressWarnings("JdkObsolete")
        void runNonGui(String testFile, String logFile, boolean remoteStart, String remoteHostsString, boolean generateReportDashboard)
                throws ConfigurationException {
            // ...
            DistributedRunner distributedRunner=new DistributedRunner(this.remoteProps);
            distributedRunner.setStdout(System.out); // NOSONAR
            distributedRunner.setStdErr(System.err); // NOSONAR
            distributedRunner.init(hosts, clonedTree);
            engines.addAll(distributedRunner.getEngines());
            testListener.setStartedRemoteEngines(engines);
            distributedRunner.start();
    }
    

    这里DistributedRunner.class的Properties参数由外部配置进来,再执行init方法获取Engines

    public static final String RETRIES_NUMBER = "client.tries"; // $NON-NLS-1$
    public static final String RETRIES_DELAY = "client.retries_delay"; // $NON-NLS-1$
    public static final String CONTINUE_ON_FAIL = "client.continue_on_fail"; // $NON-NLS-1$
       
    public DistributedRunner(Properties props) {
        remoteProps = props;
        retriesNumber = JMeterUtils.getPropDefault(RETRIES_NUMBER, 1);
        continueOnFail = JMeterUtils.getPropDefault(CONTINUE_ON_FAIL, false);
        retriesDelay = JMeterUtils.getPropDefault(RETRIES_DELAY, 5000);
    }
    
  4. DistributedRunner::start Start all engines that were previously initiated

    public void start() {
        List<String> addresses = new ArrayList<>(engines.keySet());
        start(addresses);
    }
    

    Starts a remote testing engines

    public void start(List<String> addresses) {
        // ...
        try {
            if (engine != null) {
                // runTest
                engine.runTest();
                // 记录startedEngines
                startedEngines.add(address);
            } else {
                log.warn(HOST_NOT_FOUND_MESSAGE, address);
                failedEngines.add(address);
            }
        } catch (IllegalStateException | JMeterEngineException e) { // NOSONAR already reported to user
            // 记录failedEngines
            failedEngines.add(address);
            JMeterUtils.reportErrorToUser(e.getMessage(), JMeterUtils.getResString("remote_error_starting")); // $NON-NLS-1$
        }
    }
    
  5. StandardJMeterEngine::runTest 主要执行测试的代码

    @Override
    public void runTest() throws JMeterEngineException {
            if (host != null){
                Instant now = Instant.now();
                String nowAsString = formatLikeDate(now);
                System.out.println("Starting the test on host "  // NOSONAR Intentional
                        + host + " @ " + nowAsString + " (" + now.toEpochMilli() + ')');
            }
            try {
                Thread runningThread = new Thread(this, "StandardJMeterEngine");
                runningThread.start();
            } catch (Exception err) {
                stopTest();
                throw new JMeterEngineException(err);
            }
    }
    

Comments

Content