zoukankan      html  css  js  c++  java
  • 通过jmeter测试Java性能

    通过jmeter测试Java性能

    对java与scala等代码或客户端的性能测试,不能直接发起http请求,需要实例化对象发送请求实现性能测试。

    1. jmeter提供的Java Request取样器可以控制实现JavaSamplerClient接口的类,输入参数并获取响应,利用多线程进行性能测试。
    2. 通过maven插件启动jmeter,配合部分插件管理依赖,简化每次测试环境的准备工作。

    环境搭建

    1. 搭建方式

    手动配置环境:

    1. 创建测试项目
    2. 复制jmeter lib与libext目录下的依赖文件添加到当前工程,如eclipse:鼠标选中工程点击右键 -> Build Path -> Configure Build Path -> 弹出框Libraries Tab -> 点击 Add External JARs -> 切换到待导入路径选取依赖jar
    3. 创建测试类实现JavaSamplerClient接口或继承AbstractJavaSamplerClient,并重写。 并不推荐使用实现接口的方式,使用集成AbstractJavaSamplerClient的方式比较好。
    4. 编译源码,导出为Runnable Jar File
    5. 编译后jar包放入jmeter libext目录,项目依赖jar包放入jmeter lib目录,复制项目依赖配置文件
    6. 启动jmeter,创建测试计划进行测试。

    通过maven构建配置环境:

    1. 创建测试项目
    2. 添加jmeter dependency
    3. 添加并配置插件:jmeter-maven-plugin(maven启动jmeter)、maven-dependency-plugin(copy依赖)、maven-dependency-plugin(打包项目并移动到制定目录)、maven-resources-plugin(copy项目依赖文件)
    4. 创建测试类实现JavaSamplerClient接口或继承AbstractJavaSamplerClient,并重写所需测试方法。
    5. 启动jmeter,创建测试计划进行测试。

    上面两中方式启动jmeter测试都可以:

    • 手动配置环境:从命令行启动jmeter,将所有依赖都copy进jmeter项目,对于需要较大并发的分布式测试比较好,但是每次修改变动都需要重新打包copy。
    • 通过maven构建配置环境:在项目内启动jmeter,只需要在pom.xml中配置依赖,每次有修改重新构建并启动便可,但是分布式的测试仍然需要在分布机器上发送依赖包。

    调试脚本与小并发的测试通过maven比较方便,在调试好之后将依赖分发到分布式机器上通过命令行启动agent。

    2. maven配置

    在maven的pom.xml文件中如下根据自己需要配置依赖文件和变量便可。

    • 依赖:org.apache.jmeter组织下添加的这三个依赖是编写Java Request扩展的必备。
    • jmeter-maven-plugin:maven项目中启动jmeter的插件。详细使用方法:插件配置官方文档
    • maven-dependency-plugin:maven构建依赖copy插件。
    • maven-antrun-plugin:ant插件,对编译后生成的文件再操作。
    • maven-resources-plugin:有些不是jmeter的配置依赖,在项目test/jmeter目录下无法自动copy到jmeter/bin目录下,使用这个插件copy。

    注意:maven版本需要与插件兼容,如过不兼容jmeter插件是无法运行的,如jmeter-maven-plugin:2.9.0需要maven 3.6.0+

    1. <!-- 变量配置 --> 
    2. <properties> 
    3. <!-- version --> 
    4. <jmeter.version>5.0</jmeter.version> 
    5. <jmeter.maven.plugin.version>2.9.0</jmeter.maven.plugin.version> 
    6. <maven.dependency.plugin.version>3.1.0</maven.dependency.plugin.version> 
    7. <!-- 测试结果存放路径 --> 
    8. <jmeter.result.jtl.dir>${project.build.directory}/jmeter/results</jmeter.result.jtl.dir> 
    9. <!-- 测试报表存放路径 --> 
    10. <jmeter.result.html.dir>${project.build.directory}/jmeter/html</jmeter.result.html.dir> 
    11. </properties> 
    12. <!-- Java Request Sample依赖添加 --> 
    13. <dependencies> 
    14. <dependency> 
    15. <groupId>org.apache.jmeter</groupId> 
    16. <artifactId>ApacheJMeter_core</artifactId> 
    17. <version>${jmeter.version}</version> 
    18. </dependency> 
    19. <dependency> 
    20. <groupId>org.apache.jmeter</groupId> 
    21. <artifactId>ApacheJMeter_java</artifactId> 
    22. <version>${jmeter.version}</version> 
    23. </dependency> 
    24. <dependency> 
    25. <groupId>org.apache.jmeter</groupId> 
    26. <artifactId>jorphan</artifactId> 
    27. <version>${jmeter.version}</version> 
    28. </dependency> 
    29. </dependencies> 
    30. <!-- 构建插件 --> 
    31. <build> 
    32. <plugins> 
    33. <!-- jmeter插件 --> 
    34. <plugin> 
    35. <groupId>com.lazerycode.jmeter</groupId> 
    36. <artifactId>jmeter-maven-plugin</artifactId> 
    37. <version>${jmeter.maven.plugin.version}</version> 
    38. <executions> 
    39. <execution> 
    40. <id>jmeter-tests</id> 
    41. <goals> 
    42. <goal>jmeter</goal> 
    43. </goals> 
    44. </execution> 
    45. <!-- 设置ignoreResultFailures,必须把 jmeter-check-results加上--> 
    46. <execution> 
    47. <id>jmeter-check-results</id> 
    48. <goals> 
    49. <goal>results</goal> 
    50. </goals> 
    51. </execution> 
    52. </executions> 
    53. <configuration> 
    54. <!-- 指定jmeter版本 --> 
    55. <jmeterVersion>${jmeter.version}</jmeterVersion> 
    56. <!-- 聚合报告会覆盖generateReports,指定生成CSV结果 --> 
    57. <generateReports>true</generateReports> 
    58. <resultsFileFormat>csv</resultsFileFormat> 
    59. <!-- 设置忽略失败是否停止运行 --> 
    60. <ignoreResultFailures>true</ignoreResultFailures> 
    61. <!-- 设置结果文件末尾时间戳 --> 
    62. <testResultsTimestamp>true</testResultsTimestamp> 
    63. <!-- 时间戳格式 --> 
    64. <resultsFileNameDateFormat>Y-M-D H:m:s</resultsFileNameDateFormat> 
    65. <testFilesIncluded> 
    66. <!-- 指定运行的jmeter脚本 --> 
    67. <jMeterTestFile>JmeterTest.jmx</jMeterTestFile> 
    68. </testFilesIncluded> 
    69. <!-- 指定结果生成目录 --> 
    70. <resultsDirectory>${project.build.directory}/jmeter/results</resultsDirectory> 
    71. <!-- JVM参数 --> 
    72. <jMeterProcessJVMSettings> 
    73. <xms>2048</xms> 
    74. <xmx>4096</xmx> 
    75. <arguments> 
    76. <argument>-Xprof</argument> 
    77. <argument>-Xfuture</argument> 
    78. </arguments> 
    79. </jMeterProcessJVMSettings> 
    80. </configuration> 
    81. </plugin> 
    82. <!--复制copy依赖文件--> 
    83. <plugin> 
    84. <groupId>org.apache.maven.plugins</groupId> 
    85. <artifactId>maven-resources-plugin</artifactId> 
    86. <executions> 
    87. <execution> 
    88. <id>copy-resources</id> 
    89. <phase>package</phase> 
    90. <goals> 
    91. <goal>copy-resources</goal> 
    92. </goals> 
    93. <configuration> 
    94. <encoding>UTF-8</encoding> 
    95. <!--输出路径--> 
    96. <outputDirectory> 
    97. ${project.build.directory}/jmeter/bin 
    98. </outputDirectory> 
    99. <resources> 
    100. <resource> 
    101. <!--项目中的路径--> 
    102. <directory>${project.basedir}/src/test/jmeter/</directory> 
    103. </resource> 
    104. </resources> 
    105. </configuration> 
    106. </execution> 
    107. </executions> 
    108. </plugin> 
    109. <!-- copy被测项目依赖到指定目录 --> 
    110. <plugin> 
    111. <artifactId>maven-dependency-plugin</artifactId> 
    112. <version>${maven.dependency.plugin.version}</version> 
    113. <executions> 
    114. <execution> 
    115. <id>copy-dependencies</id> 
    116. <phase>package</phase> 
    117. <goals> 
    118. <goal>copy-dependencies</goal> 
    119. </goals> 
    120. </execution> 
    121. </executions> 
    122. <configuration> 
    123. <overWriteSnapshots>true</overWriteSnapshots> 
    124. <overWriteReleases>true</overWriteReleases> 
    125. <overWriteIfNewer>true</overWriteIfNewer> 
    126. <outputDirectory>${project.build.directory}/jmeter/lib</outputDirectory> 
    127. </configuration> 
    128. </plugin> 
    129. <!-- copy编译打包后jar文件到指定目录:由于jar是在编译完成之后才能拿到,所以用ant插件在编译后copy jar --> 
    130. <plugin> 
    131. <artifactId>maven-antrun-plugin</artifactId> 
    132. <executions> 
    133. <execution> 
    134. <phase>package</phase> 
    135. <goals> 
    136. <goal>run</goal> 
    137. </goals> 
    138. <configuration> 
    139. <tasks> 
    140. <mkdir dir="${project.build.directory}/jmeter/lib/ext"/> 
    141. <copy todir="${project.build.directory}/jmeter/lib/ext" overwrite="true" > 
    142. <fileset dir="${project.build.directory}" erroronmissingdir="false"> 
    143. <include name="*.jar"/> 
    144. </fileset> 
    145. </copy> 
    146. </tasks> 
    147. </configuration> 
    148. </execution> 
    149. </executions> 
    150. </plugin> 
    151. </plugins> 
    152. </build> 

    测试例子

    1. 项目编写

    tess4j是Tesseract OCR API的Java JNA封装,除了准确性也可以测试一下处理速度。

    1. 新建maven项目。
    2. 添加tess4j maven依赖,jmeter依赖参考上面的maven配置添加
    1. <dependency> 
    2. <groupId>net.sourceforge.tess4j</groupId> 
    3. <artifactId>tess4j</artifactId> 
    4. <version>${tess4j.version}</version> 
    5. </dependency> 
    1. 创建工程目录如下:
    JavaRequestDemo
    ├── JavaRequestDemo.iml
    ├── pom.xml
    └── src
        ├── main
        │   ├── java
        │   │   └── Tess4jTest.java
        │   └── resources
        └── test
            ├── java
            └── jmeter
                ├── JmeterTest.jmx
                ├── jmeter.properties
                ├── reportgenerator.properties
                ├── saveservice.properties
                ├── system.properties
                ├── tessdata
                │   └── chi_sim.traineddata
                ├── upgrade.properties
                └── user.properties
    
    1. 下载训练库,下载地址, 不同语言的识别需要下载对应的训练库,这里下载中文的训练库chi_sim.traineddata,放置到src/test/jmeter/tessdata下
    2. test/jmeter可以放置项依赖的各种配置文件和jmeter的配置文件,会自动copy到编译后jmeter的bin目录
    3. 编写测试类Tess4jTest.java
    1. import net.sourceforge.tess4j.ITesseract; 
    2. import net.sourceforge.tess4j.Tesseract; 
    3. import net.sourceforge.tess4j.TesseractException; 
    4. import org.apache.jmeter.config.Arguments; 
    5. import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient; 
    6. import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext; 
    7. import org.apache.jmeter.samplers.SampleResult; 
    8. import org.apache.jmeter.testelement.TestElement; 
    9. import org.slf4j.Logger; 
    10. import org.slf4j.LoggerFactory; 
    11.  
    12. import java.io.File; 
    13. import java.util.Iterator; 
    14.  
    15.  
    16. /** 
    17. * public Arguments getDefaultParameters();设置可用参数及的默认值; 
    18. * public void setupTest(JavaSamplerContext arg0):每个线程测试前执行一次,做一些初始化工作; 
    19. * public SampleResult runTest(JavaSamplerContext arg0):开始测试,从arg0参数可以获得参数值; 
    20. * public void teardownTest(JavaSamplerContext arg0):测试结束时调用; 
    21. * */ 
    22. public class Tess4jTest extends AbstractJavaSamplerClient { 
    23.  
    24. public static void main(String[] args) { 
    25. Arguments arguments = new Arguments(); 
    26. arguments.addArgument("dataPath", "src/test/jmeter/tessdata1"); 
    27. arguments.addArgument("language", "chi_sim"); 
    28. arguments.addArgument("imagePath", "/tmp/20200119154923.jpg"); 
    29. JavaSamplerContext context = new JavaSamplerContext(arguments); 
    30. Tess4jTest test = new Tess4jTest(); 
    31. test.setupTest(context); 
    32. test.runTest(context); 
    33. test.teardownTest(context); 
    34. } 
    35.  
    36. private static final Logger LOG = LoggerFactory.getLogger(Tess4jTest.class); 
    37. // OCR 客户端 
    38. private ITesseract instance = new Tesseract(); 
    39. // The name of the sampler 
    40. private String name; 
    41. // Java Request参数 
    42. private String dataPath; 
    43. private String language; 
    44. private File image; 
    45.  
    46. /* 
    47. * setup操作,初始化参数 
    48. * */ 
    49. @Override 
    50. public void setupTest(JavaSamplerContext context) { 
    51. if (LOG.isDebugEnabled()) { 
    52. LOG.debug(whoAmI() + " setupTest()"); 
    53. listParameters(context); 
    54. } 
    55. dataPath = context.getParameter("dataPath"); 
    56. language = context.getParameter("language"); 
    57. image = new File(context.getParameter("imagePath")); 
    58. name = context.getParameter(TestElement.NAME); 
    59. } 
    60.  
    61. /** 
    62. * 开始测试 
    63. * */ 
    64. @Override 
    65. public SampleResult runTest(JavaSamplerContext context) { 
    66. SampleResult sample = new SampleResult(); 
    67. sample.setSampleLabel(name); 
    68. // 
    69. /* 
    70. * dataPath一定要能访问否则jvm会异常退出,可以指定相对路径与绝对路径,可能只是提示异常: 
    71. * Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again 
    72. * 1. main函数中测试相对路径是相对于src的平级目录 
    73. * 2. jmeter中是相对于jmeter启动目录,maven插件是从bin目录启动,所以如果使用相对路径一般是copy到bin目录下 
    74. * */ 
    75. instance.setDatapath(dataPath); 
    76. instance.setLanguage(language); 
    77.  
    78. sample.setSamplerData(image.getAbsolutePath()); 
    79. try { 
    80. // 开始计时 
    81. sample.sampleStart(); 
    82. // 测试的主方法 
    83. String result = instance.doOCR(image); 
    84. // 设置结果 
    85. sample.setSuccessful(true); 
    86. sample.setResponseData(result, "UTF-8"); 
    87. } catch (TesseractException e) { 
    88. LOG.error("Tess4jTest error", e); 
    89. sample.setSuccessful(false); 
    90. sample.setResponseMessage(e.toString()); 
    91. } finally { 
    92. // 计时结束 
    93. sample.sampleEnd(); 
    94. } 
    95.  
    96. if (LOG.isDebugEnabled()) { 
    97. LOG.debug(whoAmI() + " runTest()" + " Time: " + sample.getTime()); 
    98. listParameters(context); 
    99. } 
    100. return sample; 
    101. } 
    102.  
    103. /* 
    104. * 参数设置获取 
    105. * */ 
    106. @Override 
    107. public Arguments getDefaultParameters() { 
    108. Arguments params = new Arguments(); 
    109. params.addArgument("dataPath", "tessdata"); 
    110. params.addArgument("language", "chi_sim"); 
    111. params.addArgument("imagePath", "/tmp/20200119154923.jpg"); 
    112. return params; 
    113. } 
    114.  
    115. /** 
    116. * 打印参数列表 
    117. */ 
    118. private void listParameters(JavaSamplerContext context) { 
    119. Iterator<String> argsIt = context.getParameterNamesIterator(); 
    120. while (argsIt.hasNext()) { 
    121. String lName = argsIt.next(); 
    122. LOG.debug(lName + "=" + context.getParameter(lName)); 
    123. } 
    124. } 
    125.  
    126. private String whoAmI() { 
    127. return new StringBuilder() 
    128. .append(Thread.currentThread().toString()) 
    129. .append("@") 
    130. .append(Integer.toHexString(hashCode())) 
    131. .toString(); 
    132. } 
    133. } 
    134.  
    1. 测试运行,直接运行Tess4jTest.java main方法

    运行结果
    运行结果

    2. 运行测试

    1. 构建项目:mvn clean package
    2. 启动jmeter:mvn jmeter:gui
    3. 编写测试计划,单线程运行一下

    测试代码
    测试代码

    测试结果
    测试结果

    多添加几个线程的聚合报告
    多添加几个线程的聚合报告

  • 相关阅读:
    div在IOS系统和安卓系统位置不同
    js操作样式
    Css设置文字旋转
    textarea高度自适应
    html引入html页面
    举例说明$POST 、$HTTP_RAW_POST_DATA、php://input三者之间的区别
    PHP获取POST的几种方法
    PHP以xml形式获取POST数据
    使用Composer安装Symfony
    php如何以post形式发送xm并返回xmll数据
  • 原文地址:https://www.cnblogs.com/h-zhang/p/12215276.html
Copyright © 2011-2022 走看看