编程技术是改变世界的力量。
本站
当前位置:网站首页 > 后端语言 > 正文

Jmeter压测实战:Jmeter二次开发之JSF采样器实现

gowuye 2024-04-04 11:58 10 浏览 0 评论

1 前言

Jmeter是Apache基金会下的一款应用场景非常广的压力测试工具,具备轻量、高扩展性、分布式等特性。Jmeter已支持实现HTTP、FTP、JAVA、TCP、JDBC等多种采样器,方便对不同的接口类型进行请求测试及压力测试。如果被测试的接口Jmeter当前不支持,那就需要单独开发自定义采样器实现接口的请求调用,比如JSF这种京东自研的RPC类接口,或者京东JMQ消息队列接口。

本文介绍如何开发Jmeter自定义采样器,同时深刻理解Jmeter的插件化机制及高扩展性特性。

备注:JSF是京东自研的RPC服务框架,类似于开源的dubbo服务的分布式框架,具备轻量级,更佳的性能,兼容旧版本协议等优化特性。RPC框架负责屏蔽底层的传输方式(TCP或UDP)、序列号方式(XML/JSON/二进制)和通信细节,从而让程序员专注于业务的实现。

2 开发具备能力

本文Jmeter的二次开发,需要人员具备以下能力:

  • Java基础开发(包括GUI API)
  • Maven基本使用
  • Jmeter基本使用

3 实战整体流程图

4 采样器GUI实现

4.1 新建项目

本次开发依赖版本

  • JDK 1.8.0
  • Maven 3.6.3
  • Jmeter 5.4.3

新建maven项目,这里项目名为:JSF_Sampler

因为是基于Jmeter的扩展,需要依赖包Jmeter两个核心包,分别是:

  • ApacheJMeter_core
  • ApacheJMeter_java

这里还依赖了支持JSF调用的三方包
pom.xml文件核心配置如下

<groupId>com.jd.jmeter.jsf</groupId>
<artifactId>JSF_Sampler</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <jmeter-version>5.4.3</jmeter-version>
</properties>
<dependencies>
<!-- Jmeter核心依赖包,提供核心API接口 -->
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_core</artifactId>
            <version>${jmeter-version}</version>
        </dependency>
       <!-- 提供Java request等sampler API接口 -->
        <dependency>
            <groupId>org.apache.jmeter</groupId>
            <artifactId>ApacheJMeter_java</artifactId>
            <version>${jmeter-version}</version>
        </dependency>
        <dependency>
       <!-- JD内部工具包,内部封装了JSF接口的调用 -->
            <groupId>com.jd.qa</groupId>
            <artifactId>selena-core</artifactId>
            <version>0.0.36-SNAPSHOT</version>
            <exclusions>
                <exclusion>
                    <artifactId>core-utils</artifactId>
                    <groupId>com.jd.qa</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.jd.qa</groupId>
            <artifactId>core-utils</artifactId>
            <version>0.0.4.1-SNAPSHOT</version>
        </dependency>
    </dependencies>

4.2 继承实现AbstractSamplerGui类

实现类依次实现以下几个步骤

  1. 新建实现类并继承 AbstractSamplerGui
    注意:实现类的包名必须包含xxx.gui.xxx,否则无法加载自定义的GUI实现类。
  2. 初始化GUI组件,GUI使用Jmeter封装好的组件,界面元素包括:
    杰夫接口名、杰夫别名、杰夫方法及入参
  3. 同时需要重写以下几个方法
  • getStaticLabel()
  • createTestElement()
  • modifyTestElement()
  • configure()
  • clearGui()

重写方法功能及实现代码如下:

    /**
     * GUI中显示的sampler的名称
     */
    @Override
    public String getStaticLabel(){
        return "JSF Sampler";
    }
/**
 * 将界面中的数据设置到新建的sampler实例
 */
  @Override
    public TestElement createTestElement() {
        JsfSampler jsfSampler = new JsfSampler();
        this.setUpSamplerProp(jsfSampler);
        return jsfSampler;
    }
/**
 * 将界面中测试数据设置到新建的sampler实例
 */
    @Override
    public void modifyTestElement(TestElement testElement) {
        JsfSampler jsfSampler = (JsfSampler) testElement;
        this.setUpSamplerProp(jsfSampler);
    }
   /**
    * 界面与sampler之间的数据交换
    * 特别注意:一定要先调用父类的configure方法,会交换默认的一些数据
    */
    @Override
    public void configure(TestElement element) {
        super.configure(element);
        JsfSampler jsfSampler = (JsfSampler) element;
        this.interfaceField.setText(jsfSampler.getJsfInterfaceName());
        this.aliasField.setText(jsfSampler.getJsfAliasName());
        this.methodField.setText(jsfSampler.getJsfMethod());
        this.textMessage.setText(jsfSampler.getJsfBody());
    }
    /**
     * 界面reset时,可以显示默认值
     * 特别注意:一定要先调用父类的configure方法,会reset一些默认的数据
     */
    @Override
    public void clearGui() {
        super.clearGui();
        this.interfaceField.setText("com.jd.ldop.oms.api.order.OrderApi");
        this.aliasField.setText("oms-production");
        this.methodField.setText("receiveOrderInfo");
        this.textMessage.setText("{\n" +
                "\"preNum\":10,\n" +
                "\"customerCode\":\"010K258778\",\n" +
                "\"orderType\":\"0\"\n" +
                "}");
    }

最终GUI页面元素如下,即JSF接口四要素:接口名、别名、方法、入参

5 采样器核心调用实现

5.1 新建采样器实现类

  • 新建实现类并继承 AbstractSampler,同时实现接口TestStateListener
  • 注意:采样器实现类的包名必须包含xxx.functions.xxx,否则无法加载自定义的Sampler实现类。
  • 实现Sampler参数属性getter、setter方法

5.2 重写采样器核心方法

实现Sampler以下几个方法,具体方法实现见下方代码

  • sample()
  • testStarted()
  • testStarted(String s)
  • testEnded()
  • testEnded(String s)
    //以下四个方法空实现重写即可,但是必须要写,否则无法识别 
    @Override
    public void testStarted() {
    }
    @Override
    public void testStarted(String s) {
    }
    @Override
    public void testEnded() {
        this.testEnded("local");
    }
    @Override
    public void testEnded(String s) {
    }
 /**
  * 核心实现方法,此方法实现对被测接口的请求方法及返回处理
  * 其中,SampleResult封装了控制请求的发送、response结果处理的方法
  */
 @Override
    public SampleResult sample(Entry entry) {
        SampleResult sampleResult = new SampleResult();
        sampleResult.setSampleLabel(getName());
   //请求发送开始
        sampleResult.sampleStart();

        String aliasName = getJsfAliasName().split(";")[0];
        String ip = getJsfAliasName().split(";")[1].split(":")[0];
        String port = getJsfAliasName().split(";")[1].split(":")[1];
        try {
//这里使用了封装好请求JSF的包,只需要传入JSF四要素即可
            JsfBuilder jsfBuilder = JsfBuilder
                    .builder()
                    .aliasName(aliasName)
                    .interfaceName(getJsfInterfaceName())
                    .methodName(getJsfMethod())
                    .prams(getJsfBody())
                    .ip(ip)
                    .port(port)
                    .build();
            String jsfRes = jsfBuilder.hr();
//请求发送结束
            sampleResult.sampleEnd();
//处理返回的response
            sampleResult.setSuccessful(true);
            sampleResult.setResponseCodeOK();
            sampleResult.setResponseCode("SUCCESS");
            sampleResult.setResponseMessage(jsfRes);
            sampleResult.setResponseData(jsfRes,null);
        } catch (BusinessException e) {
            sampleResult.sampleEnd();
            sampleResult.setSuccessful(false);
            sampleResult.setResponseCode("FAIL");
            sampleResult.setResponseMessage("Exception" + e);
            e.printStackTrace();
            log.error("JSF接口请求报错");
        }
        return sampleResult;
    }

5.3 最终项目结构

6 Jmeter加载扩展包

以上开发完成,打包此项目,注意这里的打包要包含依赖包。

6.1 maven构建配置

<build>
        <finalName>${project.artifactId}</finalName>
        <defaultGoal>install</defaultGoal>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>assemble-all</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

6.2 项目打包

打包指令如下

mvn package -Dmaven.test.skip=true

6.3 Jmeter加载扩展包

将打包后的扩展包放置到Jmeter的ext目录:apache-jmeter-5.4.3/lib/ext/

启动Jmeter后,Jmeter会自动加载ext目录中的扩展包,可以从日志控制台看到初始化GUI日志

7 测试JSF调用

7.1 新建采样器

新建线程组->新建采样器->JSF Sampler (本次新增的采样器)

7.2 配置采样器请求参数及结果树

配置JSF请求参数如下

7.3 发送请求后查看结果树

发送请求后查看结果树

8 总结

本文通过自定义采样器实现了JSF接口的调用,希望通过本项目大家可以学习到:
如何二次开发Jmeter,实现自己特有的采样器。
理解为何官方介绍Jmeter是插件化的,高扩展性特性。
更好的理解Jmeter内部处理机制。

9 思考

  • Jmeter的HTTP采样器的实现方法是如何实现的
  • 如何实现定制化Jmeter的HTTP采样器支持HTTPs

作者:京东物流 苗浩冲

相关推荐

PHPMailer远程命令执行漏洞分析

摘要:PHPMailer是一个强大的PHP编写的邮件发送类,但近日被爆出远程命令执行漏洞,该漏洞实际上是什么,有何种影响,本文对该漏洞进行了分析及验证方法,并给出防护方案。0x00漏洞概要PHPMa...

「安全漏洞」DedeCMS-5.8.1 SSTI模板注入导致RCE

漏洞类型SSTIRCE利用条件影响范围应用漏洞概述2021年9月30日,国外安全研究人员StevenSeeley披露了最新的DedeCMS版本中存在的一处SQL注入漏洞以及一处SSTI导致的RCE...

回顾使用PHP原生发送电子邮件(终)文件附件

FileAttachments文件附件Fileattachmentsworkjustlikemixedemail,exceptthatadifferentcontenttyp...

php-fpm.conf &amp; php.ini 安全优化实践

0x01关于php其历史相对已经比较久远了,这里也就不废话了,属弱类型中一种解释型语言除了web开发以及写些简单的exp,暂未发现其它牛逼用途,暂以中小型web站点开发为主另外,低版本的php自身...

linux 安全配置 ossec 开源检测

linux安全配置ossec开源检测一:介绍主要功能有日志分析、完整性检查、rootkit检测、基于时间的警报和主动响应。除了具有入侵检测系统功能外,它还一般被用在SEM/SIM(安全事件管理(...

PHP使用PHPMailer发送验证码邮件的方法与调用逻辑

首先我们需要下载PHPMailer:https://github.com/PHPMailer/PHPMailer一般情况下我们只需要压缩包中的src文件夹中的文件,并保存至根目录即可:设置一个文件,如...

回顾使用PHP原生发送电子邮件(一)

IwishIcouldremembertheveryfirstemailmessageIeversent.Unfortunately,thetruthisthatI...

PHPMAILER实现PHP发邮件功能php实例

这篇文章主要为大家详细介绍了PHPMAILER实现PHP发邮件功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下本文实例为大家分享了PHPMAILER实现PHP发邮件功能的具体代码,供大家参考,具...

500道网络安全面试题集锦(附答案)

本篇文章内容为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,但是无论如何都无法覆盖所有的面试问题,更多的还是希望由点达面,查漏补缺,然后祝各位前程似锦,都能找到自己满意的工作!一、We...

网站放家里,随处看电影「Apache+php+ssl 安装和配置」

  使用5G网络,随处都可以看到放自己家里电脑的视频。这个功能很容易实现,不需要太多的专业知识,也不需要额外花钱。如果确实需要,最多花不到两百块钱买一台旧电脑放家里,做个网站,就能解决全部问题,Fre...

Windows2008中 Magic Winmail Server提权

MagicWinmailServer是安全易用全功能的邮件服务器软件,不仅支持SMTP/POP3/IMAP/Webmail/LDAP(公共地址簿)/多域/发信认证/反垃圾邮件/邮件过滤/邮件组...

利用PHPmailer发送邮件

早上帮朋友做一个收集客户联系方式的页面,要求能实时推送信息给管理员。刚开始想到做后台管理,因为时间紧,做后台是赶不上了。想过通过短信发送,成本太高,否决了。。。灵机一动,客户提交时直接把信息发送到邮箱...

phpmailer发送邮件

phpmailer发送邮件PHP内置的mail函数使用起来不够方便,另外受其他语言的影响,博主更偏好面向对象的包管理模式,因此phpmailer成为了我用PHP发送邮件的首选,这里分享给大家。库导入这...

PHP初级教程:读取输入

PHP读取输入:Form:?formaction="welcome.php"method="post">Name:(inputtype="text...

php filter 验证Email,Url,Ip格式

今天发现一个非常好用的函数东西,filter过滤器,用于验证和过滤来自非安全来源的数据,比如用户的输入。验证Email:$email='1234567@qq.com';if(!filter_v...

取消回复欢迎 发表评论: