淘先锋技术网

首页 1 2 3 4 5 6 7

1、Jmeter自定义取样器扩展类

Jmeter提供默认界面(AbstractJavaSamplerClient)和自定义界面的(AbstractSamplerGui)两种自定义取样器的插件开发方式,对于复杂的压测任务,可以通过自定义取样器的方式来实现。
本文通过压测SpringBoot的http接口演示两个自定义扩展类的实现方式:

2、SpringBoot服务器端http测试例子

maven项目工程,pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.penngo.example</groupId>
    <artifactId>gateway-service</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <name>gateway-service</name>
    <description>https://blog.csdn.net/penngo</description>
    <properties>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
        <java.version>11</java.version>
        <spring-boot.version>2.7.2</spring-boot.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>com.penngo.example.service.Service2App</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

http接口示例代码,Service2App.java

package com.penngo.example.service;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

@SpringBootApplication
public class Service2App {
    public static void main(String[] args) {
        SpringApplication.run(Service2App.class, args);
    }

    @RestController
    public class HelloController {
        @GetMapping("/test")
        public Map test(HttpServletRequest request){
            String page = request.getParameter("page");
            String keyword = request.getParameter("keyword");
            String userid = "";
            Cookie[] cookies = request.getCookies();
            if (cookies != null) {
                for(Cookie cookie:cookies){
                    if(cookie.getName().equals("userid")){
                        userid = cookie.getValue();
                        break;
                    }
                }
            }
            Map<String, String> data = new HashMap<>();
            data.put("page", page);
            data.put("keyword", keyword);
            data.put("userid", userid);
            return data;
        }
    }
}

3、自定义取样器实现

两种扩展的实现代码都在同一个maven工程里面,pom.xml代码:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.test.jmeter</groupId>
    <version>1.0.0</version>
    <artifactId>jmter_test</artifactId>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <maven.compiler.source>11</maven.compiler.source>
        <maven.compiler.target>11</maven.compiler.target>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.jsoup</groupId>
            <artifactId>jsoup</artifactId>
            <version>1.15.2</version>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.5</version>
        </dependency>
        <!-- 注意与Jmeter的版本一致 -->
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>5.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>5.4.3</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.17.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.17.2</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.7.36</version>
        </dependency>

    </dependencies>
</project>

3.1、默认界面的AbstractJavaSamplerClient扩展实现

可通过getDefaultParameters()接口,实现在默认界面上配置参数,SampleResult负责记录样本结果,TestHttpSampler.java代码:

package com.test.jmeter;

import cn.hutool.json.JSONUtil;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class TestHttpSampler extends AbstractJavaSamplerClient {
    private static final Logger log = LoggerFactory.getLogger(TestHttpSampler.class);
    @Override
    public SampleResult runTest(JavaSamplerContext javaSamplerContext) {

        String url = javaSamplerContext.getParameter("url");
        String userid = javaSamplerContext.getParameter("userid");

        Map<String, String> cookieMap = new HashMap();
        cookieMap.put("userid", userid);

        SampleResult sampleResult = new SampleResult();
        sampleResult.setSampleLabel("JavaSamplerClient请求查询");
        sampleResult.sampleStart();
        try {
            Map<String, String> data = data();
            sampleResult.setRequestHeaders(JSONUtil.toJsonStr(data));

            var res = Jsoup.connect(url)
                    .header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
                    .ignoreContentType(true)
                    .cookies(cookieMap)
                    .data(data)
                    .method(Connection.Method.GET)
                    .execute();
            String body = res.body();
            log.info(body);
            sampleResult.setSuccessful(true);
            sampleResult.setResponseCode("200");
            sampleResult.setResponseData(body, "UTF-8");
            sampleResult.setResponseCodeOK();
        }
        catch(Exception e){
            log.error("runTest error:",e);
            sampleResult.setResponseCode("500");
            sampleResult.setSuccessful(false);
            sampleResult.setResponseData("exception," + e.getMessage(), "UTF-8");
        }
        sampleResult.sampleEnd();
        return sampleResult;
    }
    private Map<String, String> data(){
        Random r = new Random();
        String page = String.valueOf((r.nextInt(5) + 1));
        StringBuffer keyword = new StringBuffer();
        String str = "abcdefghijklmnopqrstuvwxyz";

        for(int i = 0; i < 7; i++){
            keyword.append(str.toCharArray()[r.nextInt(str.length())]);
        }

        Map<String, String> data = new HashMap<>();
        data.put("page",page);
        data.put("keyword",keyword.toString());
        return data;
    }
    public Arguments getDefaultParameters() {
        Arguments arguments = new Arguments();
        arguments.addArgument("url", "");
        arguments.addArgument("userid", "");
        return arguments;
    }
}

3.2、自定义界面的AbstractSamplerGui扩展实现

自定义界面的UI库是基于swing,可以使用所有的swing组件

package com.test.jmeter;

import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.*;
import java.awt.*;

public class TestGuiHttpSampler extends AbstractSamplerGui {
    private static final Logger log = LoggerFactory.getLogger(TestGuiHttpSampler.class);
    private JTextField urlField = null;
    private JTextField useridField = null;

    public TestGuiHttpSampler(){
        urlField = new JTextField();
        useridField = new JTextField();
        initUI();
    }

    private void initUI(){
        JPanel topPanel = new JPanel(new GridBagLayout());
        topPanel.add(new JLabel("http参数"), new GB(0,0,1,1).setInsets(5));
        topPanel.add(new JLabel("访问地址:"), new GB(0,1,1,1).setInsets(5));
        topPanel.add(urlField, new GB(1,1,1,1).setInsets(5).setFill(GB.BOTH).setWeight(100,0));
        topPanel.add(new JPanel(), new GB(0,2,2,1).setInsets(5).setFill(GB.BOTH).setWeight(100,100));

        JPanel bottomPanel = new JPanel(new GridBagLayout());
        bottomPanel.add(new JLabel("Cookie参数"), new GB(0,0,1,1).setInsets(5));
        bottomPanel.add(new JLabel("用户id:"), new GB(0,1,1,1).setInsets(5));
        bottomPanel.add(useridField, new GB(1,1,1,1).setInsets(5).setFill(GB.BOTH).setWeight(100,0));
        bottomPanel.add(new JPanel(), new GB(0,2,2,1).setInsets(5).setFill(GB.BOTH).setWeight(100,100));

        JSplitPane splitPane = new JSplitPane();
        splitPane.setOneTouchExpandable(true);
        splitPane.setContinuousLayout(true);
        log.info("====TestGuiHttpSampler size:" + this.getSize());
        splitPane.setDividerLocation(50);
        splitPane.setPreferredSize(this.getSize());
        splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
        splitPane.setTopComponent(topPanel);
        splitPane.setBottomComponent(bottomPanel);

        setLayout(new BorderLayout());
        add(splitPane, BorderLayout.CENTER);
    }

    @Override
    public String getLabelResource() {
        return null;
    }

    @Override
    public TestElement createTestElement() {
        TestGuiSampler sample = new TestGuiSampler();
        return sample;
    }

    @Override
    public void modifyTestElement(TestElement testElement) {
        testElement.clear();
        configureTestElement(testElement);
        testElement.setProperty(TestGuiSampler.URL, urlField.getText());
        testElement.setProperty(TestGuiSampler.USERID, useridField.getText());
    }

    @Override
    public boolean canBeAdded() {
        return super.canBeAdded();
    }
    @Override
    public String getStaticLabel() {
        return "TestGuiHttpSampler测试";
    }
    @Override
    public void clearGui() {
        super.clearGui();
        urlField.setText("");
        useridField.setText("");
    }
}

3、自定义取样器运行效果

工程项目打包,把jmter_test-1.0.0.jar、jsoup-1.15.2.jar、hutool-all-5.8.5.jar三个包扔到apache-jmeter-5.4.3\lib\ext目录中,重新启动Jmeter。

3.1、AbstractJavaSamplerClient运行效果

在线程组上鼠标右键,弹出菜单中选择“取样器->Java请求中”,在面板的下拉框中可以看到实现的扩展类名并选择。
在这里插入图片描述

在这里插入图片描述

3.2、AbstractSamplerGui运行效果

在线程组上右键,在取样器的子菜单中,能看到实现的扩展类"TestGuiHttpSampler测试",选择即可
在这里插入图片描述

在这里插入图片描述

3.3、监听器-查看结果树

在这里插入图片描述

3.4、监听器-聚合报告

在这里插入图片描述
源码下载