开发自定义jmeter sampler 插件

目录

一、编写sampler代码

二、sampler运行方式


有时候,jmeter自带的sampler插件不能满足需求,需要自己开发插件,比如,不是压测http接口,而是压测代码库的git clone、git push命令时。本文记录git push压测的自定义sampler开发方法。

一、编写sampler代码

第一步:创建maven项目,在pom文件中引入git包和jmeter核心包的依赖

<dependencies>
       <!-- jgit package -->
        <dependency>
            <groupId>org.eclipse.jgit</groupId>
            <artifactId>org.eclipse.jgit</artifactId>
            <version>5.5.1.201910021850-r</version>
        </dependency>

        <!-- jmeter packages-->
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>5.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>5.0</version>
        </dependency>
    </dependencies>

第二步:创建一个类继承AbstractSamplerGui,该类是编写jmeter sampler的UI界面的,可以定义sampler需要的入参,

注意:里面涉及到的sampler要与后面自己创建的自定义sampler对应

package com.xx.gitPush.sampler;

import com.xx.gitPush.sampler.GitPushSampler;
import org.apache.jmeter.gui.util.HorizontalPanel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
import org.apache.jmeter.testelement.TestElement;

import javax.swing.*;
import java.awt.*;
import java.util.logging.Logger;

public class GitPushSamplerUI extends AbstractSamplerGui {

    private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger("GitPushSampler");
    private JTextField server;
    private JTextField port;
    private JTextField username;
    private JTextField password;
    private JTextField cookie;
    private JTextField filesNum;
    private JTextArea gitPushGroups;

    public GitPushSamplerUI() {
        super();
        init();
    }

    private void init() {
        createPanel();
    }

    private JPanel getServerPanel() {
        server = new JTextField(10);
        JLabel label = new JLabel("host server:");
        label.setLabelFor(server);

        JPanel panel = new HorizontalPanel();
        panel.add(label, BorderLayout.WEST);
        panel.add(server, BorderLayout.CENTER);
        return panel;
    }

    private JPanel getPortPanel() {
        port = new JTextField(10);

        JLabel label = new JLabel("server port:");
        label.setLabelFor(port);

        JPanel panel = new HorizontalPanel();
        panel.add(label, BorderLayout.WEST);
        panel.add(port, BorderLayout.CENTER);

        return panel;
    }

    private JPanel getUsernamePanel() {
        username = new JTextField(20);
        JLabel label = new JLabel("username:");
        label.setLabelFor(username);

        JPanel panel = new HorizontalPanel();
        panel.add(label, BorderLayout.WEST);
        panel.add(username, BorderLayout.CENTER);
        return panel;
    }

    private JPanel getPasswordPanel() {
        password = new JTextField(20);
        JLabel label = new JLabel("password:");
        label.setLabelFor(password);

        JPanel panel = new HorizontalPanel();
        panel.add(label, BorderLayout.WEST);
        panel.add(password, BorderLayout.CENTER);
        return panel;
    }
    private JPanel getCookiePanel() {
        cookie = new JTextField(20);
        JLabel label = new JLabel("cookie:");
        label.setLabelFor(cookie);

        JPanel panel = new HorizontalPanel();
        panel.add(label, BorderLayout.WEST);
        panel.add(cookie, BorderLayout.CENTER);
        return panel;
    }
    private JPanel getFilesNum() {
        filesNum = new JTextField(10);
        JLabel label = new JLabel("files Num:");
        label.setLabelFor(filesNum);

        JPanel panel = new HorizontalPanel();
        panel.add(label, BorderLayout.WEST);
        panel.add(filesNum, BorderLayout.CENTER);
        return panel;
    }

    private JPanel getGitPushGroupsPanel() {
        gitPushGroups = new JTextArea(20, 20);
        JLabel label1 = new JLabel("gitPushGroups:");
        label1.setLabelFor(gitPushGroups);
        JPanel panel1 = new HorizontalPanel();
        panel1.add(label1, BorderLayout.WEST);
        panel1.add(gitPushGroups, BorderLayout.CENTER);
        return panel1;
    }

    private void createPanel() {
        JPanel settingPanel = new VerticalPanel(8, 0);
        settingPanel.add(getServerPanel());
        settingPanel.add(getPortPanel());
        settingPanel.add(getUsernamePanel());
        settingPanel.add(getPasswordPanel());
        settingPanel.add(getCookiePanel());
        settingPanel.add(getFilesNum());
        //settingPanel.add(getGitCloneRepos());
        settingPanel.add(getGitPushGroupsPanel());

        JPanel dataPanel = new JPanel(new BorderLayout(8, 0));
        dataPanel.add(settingPanel, BorderLayout.NORTH);
        setLayout(new BorderLayout(0, 8));
        setBorder(makeBorder());
        add(makeTitlePanel(), BorderLayout.NORTH); // Add the standard title
        add(dataPanel, BorderLayout.CENTER);
    }

    //implement
    public String getLabelResource() {
        // TODO Auto-generated method stub
        throw new IllegalStateException("This shouldn't be called");
    }

    public TestElement createTestElement() {
        // TODO Auto-generated method stub
        GitPushSampler sampler = new GitPushSampler();
        modifyTestElement(sampler);
        return sampler;
    }

    public void modifyTestElement(TestElement arg0) {
        // TODO Auto-generated method stub
        arg0.clear();
        configureTestElement(arg0);
        arg0.setProperty(GitPushSampler.SERVER, server.getText());
        arg0.setProperty(GitPushSampler.PORT, port.getText());
        arg0.setProperty(GitPushSampler.USERNAME, username.getText());
        arg0.setProperty(GitPushSampler.PASSWORD, password.getText());
        arg0.setProperty(GitPushSampler.COOKIE, cookie.getText());
        arg0.setProperty(GitPushSampler.FILESNUM,filesNum.getText());
        arg0.setProperty(GitPushSampler.GITPUSHGROUPS, gitPushGroups.getText());
    }

    @Override
    public String getStaticLabel() {
        return "GitPushSampler";
    }

    @Override
    public void clearGui() {
        super.clearGui();
        server.setText("");
        port.setText("");
        username.setText("");
        password.setText("");
        cookie.setText("");
        filesNum.setText("");
        //gitCloneRepos.setText("");
        gitPushGroups.setText("");

    }

    @Override
    public void configure(TestElement element) {
        super.configure(element);
        server.setText(element.getPropertyAsString(GitPushSampler.SERVER));
        port.setText(element.getPropertyAsString(GitPushSampler.PORT));
        username.setText(element.getPropertyAsString(GitPushSampler.USERNAME));
        password.setText(element.getPropertyAsString(GitPushSampler.PASSWORD));
        cookie.setText(element.getPropertyAsString(GitPushSampler.COOKIE));
        filesNum.setText(element.getPropertyAsString(GitPushSampler.FILESNUM));
        //gitCloneRepos.setText(element.getPropertyAsString(GitPushSampler.GITGLONEREPOS));
        gitPushGroups.setText(element.getPropertyAsString(GitPushSampler.GITPUSHGROUPS));

    }
}

第三步:创建自己的sampler,继承自AbstractSampler,这里实现接受界面配置参数的的类处理业务逻辑的方法代码

package com.xx.gitPush.sampler;

import com.xx.gitPush.repo.Repo;
import com.xx.gitPush.repo.RepoClient;
import com.xx.gitPush.utils.TimeUtils;
import org.apache.jmeter.samplers.AbstractSampler;
import org.apache.jmeter.samplers.Entry;
import org.apache.jmeter.samplers.SampleResult;
import org.eclipse.jgit.api.Git;
import java.util.logging.Level;
import java.util.logging.Logger;


public class GitPushSampler extends AbstractSampler {

    private static final long serialVersionUID = 1L;
    private static final Logger log = Logger.getLogger("GitPushSampler");
    // The name of the property used to hold our data
    public static final String SERVER = "server.text";
    public static final String PORT = "port.text";
    public static final String USERNAME = "username.text";
    public static final String PASSWORD = "password.text";
    public static final String COOKIE = "cookie.text";
    public static final String FILESNUM = "filesNum.text";
    public static final String GITPUSHGROUPS = "gitPushGroups.text";

    public String getServer() {
        return getPropertyAsString(SERVER);
    }
    public String getPort() {
        return getPropertyAsString(PORT);
    }
    public String getUsername() {
        return getPropertyAsString(USERNAME);
    }
    public String getPassword() {
        return getPropertyAsString(PASSWORD);
    }
    public String getCookie() {
        return getPropertyAsString(COOKIE);
    }
    public String getFilesNum() {return getPropertyAsString(FILESNUM);}

    public String getGitPushGroups(){
        return getPropertyAsString(GITPUSHGROUPS);
    }

    private String getTitle() {
        return this.getName();
    }
    public GitPushSampler(){
        setName("GitPushSampler");
    }
    private void trace(String s) {
        String tl = getTitle();
        String tn = Thread.currentThread().getName();
        String th = this.toString();
    }

    public SampleResult sample(Entry e) {
        trace("sample()");
        SampleResult mainRes = new SampleResult();
        String server = getServer();
        String port = getPort();
        String username = getUsername();
        String password = getPassword();
        String cookie = getCookie();
        String filesNum = getFilesNum();
        String gitPushGroups = getGitPushGroups();
        boolean isOK = false;
        String response = null;

        mainRes.setSampleLabel(getTitle());
        mainRes.sampleStart();  //获取start time

        for (String gitPushGroup : gitPushGroups.split("\n")) {
            SampleResult subGitPushRes = new SampleResult();

            try {

                subGitPushRes.sampleStart();

                String magic = TimeUtils.generateFormatTimeString();
                RepoClient client = new RepoClient(server, username, password, cookie);

                String repoName = server + gitPushGroup + "/" + "repo_" + magic + "_" + Thread.currentThread().getId();
                System.out.println("repoName: " + repoName);
                Repo repo = new Repo(repoName);
                client.createRepo(client.getCookie(), repo);

            
                String result = String.format("push %s-%s-%s to %s under %s successfully",
                        repo.getRepoNamespace(), repo.getRepoName(), repo.getRepoBranch(), repo.getRepoDir(), repo.getRepoDir());
                log.info(String.format("server:%s, port:%s, username:%s", server, port, username));
                log.info("subGitPushRes: " + subGitPushRes);

                Git git = client.gitClone(repo);
                System.out.println("FILESNUM:" + filesNum);
                String file = client.getPushFile(Integer.parseInt(filesNum));
                String push_file = "/tmp/" + repo.getRepoDir() + "/" + magic + "_" + Thread.currentThread().getId() + "_" + file;
                client.copyFile(file, push_file);
                System.out.println("/tmp/" + repo.getRepoDir());


                long start = System.currentTimeMillis();
                client.gitPush(repo, push_file);
                long end = System.currentTimeMillis();
                long duration = end - start;
                subGitPushRes.setLatency(duration);
                subGitPushRes.setSampleLabel(String.format("%s-%s", repo.getRepoNamespace(), repo.getRepoName()));
                System.out.println("duration: " + duration);
                subGitPushRes.sampleEnd();
                subGitPushRes.setSamplerData(String.format("server:%s, port:%s, username:%s, repo: %s", server, port, username, repo.getRepoUrl()));
                subGitPushRes.setResponseData(result, null);
                subGitPushRes.setDataType(SampleResult.TEXT);
                subGitPushRes.setResponseOK();

                // clean up
                client.cleanPush(repo, push_file);
                client.deleteRepo(server, repo.getRepoNamespace(),repo.getRepoName(),client.getCookie());
                isOK = true;
            } catch (Exception ex) {
                log.log(Level.INFO, "", ex);
                subGitPushRes.setResponseCode("500");
                subGitPushRes.setSuccessful(false);
                subGitPushRes.setResponseMessage(ex.toString());
            }

            mainRes.addSubResult(subGitPushRes, false);
        }
        mainRes.sampleEnd();
        mainRes.setResponseOK();
        return mainRes;

    }
}

第四步:自定义sampler里用到其他方法或utils方法可以封装到其他包下进行调用,整体项目目录结构如下:

二、sampler运行方式

方式一:使用本地jmeter,通过导入到jmeter里运行

1、将代码打包,注意,打包时需要将整个项目依赖的其他包一起打包,否则在jmeter中执行时会报错找不到各种依赖包,打包方式在pom里定义:

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <!--这部分可有可无,加上的话则直接生成可运行jar包 -->
                    <!--<archive> -->
                    <!--<manifest> -->
                    <!--<mainClass>${exec.mainClass}</mainClass> -->
                    <!--</manifest> -->
                    <!--</archive> -->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>

2、将打的jar包放在jmeter/lib/ext下,注意,有两个包,需要将包含依赖包的一个放进去:将GitPushSampler-1.0-SNAPSHOT-jar-with-dependencies.jar放在jmeter/lib/ext里

3、打开jmeter 界面,创建线程组——>创建取样器——>选择GitPushSampler

4、在界面上填写参数host、端口、用户名、密码、cookie、文件数目、已存在的push仓库、线程数等参数

 5、进行压测

方式二:脱离本地jmeter,在项目里直接以命令方式运行(项目里直接放入jmeter安装包)

1、将对应版本的jmeter放入项目,本文使用5.0,见上面目录结构

2、将项目打的jar包放入jmeter5.0/lib/ext下

3、创建jmx脚本:gitPushScript.jmx,填写参数host、端口、用户名、密码、cookie、文件数目、已存在的push仓库,以及线程数等

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.0 r1840935">
  <hashTree>
    <TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
      <stringProp name="TestPlan.comments"></stringProp>
      <boolProp name="TestPlan.functional_mode">false</boolProp>
      <boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
      <boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
      <elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
        <collectionProp name="Arguments.arguments"/>
      </elementProp>
      <stringProp name="TestPlan.user_define_classpath"></stringProp>
    </TestPlan>
    <hashTree>
      <ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
        <stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
        <elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
          <boolProp name="LoopController.continue_forever">false</boolProp>
          <intProp name="LoopController.loops">1</intProp>
        </elementProp>
        <stringProp name="ThreadGroup.num_threads">2</stringProp>
        <stringProp name="ThreadGroup.ramp_time">1</stringProp>
        <boolProp name="ThreadGroup.scheduler">false</boolProp>
        <stringProp name="ThreadGroup.duration">4</stringProp>
        <stringProp name="ThreadGroup.delay"></stringProp>
      </ThreadGroup>
      <hashTree>
        <com.xx.gitPush.sampler.GitPushSampler guiclass="com.xx.gitPush.sampler.GitPushSampler" testclass="com.xx.gitPush.sampler.GitPushSampler" testname="GitPushSampler" enabled="true">
          <stringProp name="server.text">http://github.com/</stringProp>
          <stringProp name="port.text"></stringProp>
          <stringProp name="username.text">zhansgan</stringProp>
          <stringProp name="password.text">*****</stringProp>
          <stringProp name="cookie.text">token=AB58432AD03F654520220412103759</stringProp>
          <stringProp name="filesNum.text">6</stringProp>
          <stringProp name="gitPushGroups.text">jmeter1
jmeter2
</stringProp>
        </com.xx.gitPush.sampler.GitPushSampler>
        <hashTree>
          <ResultCollector guiclass="ViewResultsFullVisualizer" testclass="ResultCollector" testname="View Results Tree" enabled="true">
            <boolProp name="ResultCollector.error_logging">false</boolProp>
            <objProp>
              <name>saveConfig</name>
              <value class="SampleSaveConfiguration">
                <time>true</time>
                <latency>true</latency>
                <timestamp>true</timestamp>
                <success>true</success>
                <label>true</label>
                <code>true</code>
                <message>true</message>
                <threadName>true</threadName>
                <dataType>true</dataType>
                <encoding>false</encoding>
                <assertions>true</assertions>
                <subresults>true</subresults>
                <responseData>false</responseData>
                <samplerData>false</samplerData>
                <xml>false</xml>
                <fieldNames>true</fieldNames>
                <responseHeaders>false</responseHeaders>
                <requestHeaders>false</requestHeaders>
                <responseDataOnError>false</responseDataOnError>
                <saveAssertionResultsFailureMessage>true</saveAssertionResultsFailureMessage>
                <assertionsResultsToSave>0</assertionsResultsToSave>
                <bytes>true</bytes>
                <sentBytes>true</sentBytes>
                <url>true</url>
                <threadCounts>true</threadCounts>
                <idleTime>true</idleTime>
                <connectTime>true</connectTime>
              </value>
            </objProp>
            <stringProp name="filename"></stringProp>
          </ResultCollector>
          <hashTree/>
        </hashTree>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

4、创建存放报告的report的目录,编写run_push.sh脚本存放jmeter命令:

rm -rf report/gitPush; rm -rf report/result.gitPush; nohup apache-jmeter-5.0/bin/jmeter -n -t gitPushScript.jmx -l report/result.gitPush -e -o report/gitPush > GitPush.log 2>&1 &

5、命令行运行脚本、生成日志文件、结果报告

运行命令:./run_push.sh
日志文件:GitPush.log
结果报告:report目录下,html报告

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值