基于Jmeter的性能测试框架搭建

引言

谈到性能测试,部分公司连专门用于性能测试的环境都没有,更别提性能测试框架/平台了。下面,笔者就“基于Jmeter的性能测试框架搭建”这个话题,谈谈自己的一些想法。

工具

Jmeter
Influxdb
Grafana
Telegraf
Jenkins
Ant
Gitlab

理念

  • 测试人员只需专注脚本编写及性能结果分析。脚本提交Gitlab后自动触发构建,性能结果实时展现。

  • 性能测试脚本统一管理。

    性能测试框架 

 

实现方法

  • 依赖Jmeter的Backend Listener监听器,采集tps,响应时间,cpu,内存等信息至Influxdb时序数据库,然后再通过Grafana展现性能结果。

  • 依赖Jenkins的webhook插件监听push事件,即push脚本至gitlab则触发Ant构建。

一、脚本上传小工具开发


压测小工具


开始构建

为了简便测试人员操作,特开发此压测小工具,实现功能如下:

  • 上传脚本前,初始化本地git仓库。

  • 克隆git仓库。

  • 根据上传的脚本修改build.xml文件。

  • push脚本和build.xml文件。

使用JGit访问Gitlab,dom4j处理xml文件。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.tool</groupId>    <artifactId>performanceTestTool</artifactId>    <version>1.0-SNAPSHOT</version>    <build>        <plugins>            <plugin>                <groupId>org.apache.maven.plugins</groupId>                <artifactId>maven-compiler-plugin</artifactId>                <configuration>                    <source>6</source>                    <target>6</target>                </configuration>            </plugin>        </plugins>    </build>

    <repositories>        <repository>            <id>jgit-repository</id>            <url>https://repo.eclipse.org/content/groups/releases/</url>        </repository>    </repositories>
    <!-- Core Library -->    <dependencies>        <dependency>            <groupId>org.eclipse.jgit</groupId>            <artifactId>org.eclipse.jgit</artifactId>            <version>4.11.0.201803080745-r</version>        </dependency>
        <!-- Smart HTTP Servlet -->        <dependency>            <groupId>org.eclipse.jgit</groupId>            <artifactId>org.eclipse.jgit.http.server</artifactId>            <version>4.11.0.201803080745-r</version>        </dependency>
        <!-- AWT UI Helpers -->        <dependency>            <groupId>org.eclipse.jgit</groupId>            <artifactId>org.eclipse.jgit.ui</artifactId>            <version>4.11.0.201803080745-r</version>        </dependency>
        <!-- JUnit Test Support -->        <dependency>            <groupId>org.eclipse.jgit</groupId>            <artifactId>org.eclipse.jgit.junit</artifactId>            <version>4.11.0.201803080745-r</version>        </dependency>
        <dependency>            <groupId>dom4j</groupId>            <artifactId>dom4j</artifactId>            <version>1.6.1</version>        </dependency>    </dependencies>
</project>

clone项目至本地仓库:

    public static void cloneProject() throws Exception {
        //每次clone前先初始化        Util.deletefile(localProject);
        File file = new File(localProject);        try {            //克隆代码库命令            CloneCommand cloneCommand = Git.cloneRepository();            cloneCommand.setURI(remoteRepoURI) //设置远程URI                    .setBranch("master") //设置clone下来的分支                    .setDirectory(file) //设置下载存放路径                    .setCredentialsProvider(usernamePasswordCredentialsProvider)                    .call();        } catch (GitAPIException e) {            e.printStackTrace();        }    }

pull操作:

    public static void pullFiles() throws IOException, GitAPIException {
        //git仓库地址        Git git = new Git(new FileRepository(localProject+"/.git"));        git.pull().setRemoteBranchName("master").                setCredentialsProvider(usernamePasswordCredentialsProvider).call();    }

push操作:

    public static void pushFiles(String filePath,String commitMess) throws IOException, GitAPIException {
        File fileFrom = new File(filePath);        File fileTemp = new File(localProject);        File fileTo = new File(fileTemp.getAbsolutePath()+"/"+fileFrom.getName());        fileTo.createNewFile();
        Util.copyFiles(fileFrom,fileTo);  //拷贝脚本文件至git本地仓库
        Repository rep = new FileRepository(localProject+"\\.git");        Git git1 = new Git(rep);        git1.add().addFilepattern(fileFrom.getName()).call();  //此处必须使用本地仓库中需推送的文件名        git1.add().addFilepattern("build.xml").call();         //push修改后的build文件        //提交        git1.commit().setMessage(commitMess).call();        git1.push().setCredentialsProvider(usernamePasswordCredentialsProvider).call();    }

build.xml文件配置:

<?xml version="1.0" encoding="UTF-8" standalone="no"?><project basedir="." default="run" name="Ant">    <tstamp>        <format pattern="yyyyMMddhhmm" property="time"/>    </tstamp>    <!-- jmeter路径-->      <property name="jmeter.home" value="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1"/>    <!-- jmeter jtl测试报告生成路径-->     <property name="jmeter.result.jtl.dir" value="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\report\jtl"/>    <!-- jmeter html测试报告生成路径-->    <property name="jmeter.result.html.dir" value="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\report\html"/>    <!-- 参数化-->      <property name="ReportName" value="TestReport"/>    <property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}${time}.jtl"/>    <property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}${time}.html"/>        <target name="run">        <antcall target="test"/>        <!--性能脚本构建时,生成报告时间太长,注释掉 -->        <!-- antcall target="report"/ -->    </target>        <target name="test">        <taskdef classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" name="jmeter"/>        <jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">             <!-- 构建路径,与jenkins上工作空间配置保持一致 -->            <testplans dir="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\jenkins_jobworkspace" includes="测试.jmx"/>            <property name="jmeter.save.saveservice.output_format" value="xml"/>
        </jmeter>    </target>            <target name="report">        <xslt in="${jmeter.result.jtlName}" out="${jmeter.result.htmlName}" style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl"/>                <!-- 测试报告-->         <copy todir="${jmeter.result.html.dir}">            <fileset dir="${jmeter.home}/extras">                <include name="collapse.png"/>                <include name="expand.png"/>            </fileset>        </copy>    </target></project>

通过分析上面的build.xml文件,发现构建脚本由includes的值来定义,如果值为“*.jmx”,则会构建dir目录下所有的jmx文件。由于我们只需构建上传的脚本,那有必要修改build文件,使includes的值等于上传的脚本名称。

<testplans dir="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\jenkins_jobworkspace" includes="测试.jmx"/>

修改build文件的includes值:

    public static void modifyBuild(String filePath,String modifyName) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        DocumentBuilder db = dbf.newDocumentBuilder();        Document doc = db.parse(new File(filePath)); // 读取xml文件
        NodeList targetList = doc.getElementsByTagName("testplans");  //获取testplans节点
        for (int i = 0; i < targetList.getLength(); i++) {            Node case_node = targetList.item(i); // 第一个caseNo节点
            Element elem0 = (Element) case_node; // caseNo节点对象            String target_name = elem0.getAttribute("includes");            System.out.println("修改前includes = " + target_name); // 节点属性
            elem0.setAttribute("includes",modifyName);            String target_name1 = elem0.getAttribute("includes");            System.out.println("修改后includes = " + target_name1); // 节点属性        }        saveXml(filePath, doc);    }

至此,第一阶段的工作已完成。当然,你也可以通过Git bash来push脚本触发构建,但是你得另外想办法来控制脚本的构建,因为Ant是根据build.xml文件来指定构建哪些脚本的。

二、配置Jenkins,Gitlab
  • 安装jenkins插件。
    Ant Plugin
    Git plugin
    GitLab Plugin
    Gitlab Hook Plugin

    可以在线安装,也可以下载本地安装,下载地址
     

  • jenkins-系统配置-全局工具配置。
    配置jdk,git,ant。


    jdk


    git&ant

  • jenkins-项目-配置。
    自定义空间与build.xml设置的构建路径保持一致,jenkins构建时,会把git仓库pull到该路径下。

<testplans dir="D:\tools\PerformanceTesting\Jmeter_influxdb_grafana\apache-jmeter-3.1\TestCase\jenkins_jobworkspace" includes="测试.jmx"/>


自定义空间


git源码管理

 

注意下图的Targets需同build.xml文件一致。

​​​​​​​​​​​​​​

    <target name="run">        <antcall target="test"/>        <!--性能脚本构建时,生成报告时间太长,注释掉 -->        <!-- antcall target="report"/ -->    </target>


构建

由于依赖webhook来监听push事件触发构建,拷贝下图的URL,并在“高级”选项中生成“Secret token”,后续在gitlab添加webhook。


构建触发器


构建触发器

  • gitlab-webhook配置。
    由于只需监听push事件,所有下图只勾选了Push events“”。添加webhook后,点击“Test”进行测试,如果返回200/201,则表明webhook配置成功。


    webhook

    Image

    webhook-test

    如果不想使用Secret token配置webhook,也可按以下方式来配置:
    打开jenkins的“设置”页面,找到API Token,然后在gitlab上添加webhook url即可,结构如下图2所示(UserId:APIToken@jenkins构建器url)。


    API Token


三、配置Influxdb,Grafana,Telegraf

Influxdb+Grafana+Telegraf在笔者的另一篇文章<Jmeter排忧解难—性能测试监控>有提及,百度也大把文章,此处不再详述。

四、编写测试脚本

使用jmeter编写一个简单的测试脚本来进行测试,主要依赖Backend Listener监听器来集成influxdb。

测试脚本

测试脚本

五、性能结果分析

运行“一、脚本上传小工具开发”提及的压测小工具,就可以对性能结果做实时监控了。下图1仅对tps和响应时间做采集,由于笔者未在被测服务器上安装Telegraf,所以cpu,内存等数据暂不采集,有兴趣的童鞋可以自行探索。更详细的监控结果如图2所示。


性能测试结果


性能测试结果

六、构建日志

登录jenkins,可以查看详细的构建日志。


Jenkins构建日志

后续改进

其实以上框架还存在不少待改进之处,笔者后续再逐步解决。

  • Grafana性能图表实时展现,测试过程中需实时截图形成测试报告,不够人性化。
    解决方案:自动生成测试报告并邮件通知。

  • Grafana性能图表需测试人员实时监控,人力成本较高。
    解决方案:自动生成测试报告并邮件通知。

  • 多脚本构建的话,无法区分Grafana展现的性能图表对应哪个脚本。
    解决方案:传参区分脚本,并生成每个接口对应的测试报告。

  • 如果考虑持续监控,可加入预警功能。
    解决方案:依赖Grafana的预警功能。

  • 未能自动生成测试报告。
    解决方案:自动生成测试报告并邮件通知。

  • 需登录jenkins停止脚本构建,操作不够便利。
    解决方案:前端增加停止构建操作。

  • 每次只能提交一个脚本进行构建。
    解决方案:支持批量构建。

  • 25
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很高兴回答你的问题!为了回答这个问题,我假设你已经了解了JMeter性能测试的基础知识。 首先,我们需要选择一个开源项目来进行性能测试。在这里,我们选择了一个叫做“PetClinic”的开源项目。PetClinic是一个简单的Web应用程序,用于管理宠物诊所的数据。它是一个Spring Boot应用程序,使用MySQL数据库。 接下来,我们需要创建一个JMeter测试计划来对PetClinic进行性能测试。我们需要使用JMeter的HTTP请求,模拟多个用户同时访问PetClinic的情况。我们可以创建一个线程组,并为每个线程设置一个HTTP请求。我们还可以为每个请求设置参数,例如请求方法,请求URL,请求头,请求正文等。 在测试之前,我们需要确定性能测试的目标。我们可以设置吞吐量、响应时间、并发用户数等指标,并根据这些指标来评估PetClinic的性能。 接下来,我们需要运行测试,并收集测试结果。JMeter可以收集各种指标,例如响应时间、吞吐量、错误率等。我们可以使用JMeter的结果分析器来分析这些指标,并根据测试结果来确定PetClinic的性能。 最后,我们可以根据测试结果来优化PetClinic的性能。我们可以尝试优化数据库查询、缓存数据、使用负载均衡等技术来提高性能。然后,我们可以重新运行测试,并比较测试结果,以确定我们的优化是否有效。 以上就是一个基于JMeter性能测试的简单描述。当然,具体实现需要根据实际情况进行调整和优化。希望这能对你有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值