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. 编写测试计划,单线程运行一下

    测试代码
    测试代码

    测试结果
    测试结果

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

  • 相关阅读:
    HearthBuddy投降插件2019-11-01的使用
    正则表达式在线分析 regex online analyzer
    Tips to write better Conditionals in JavaScript
    The fileSyncDll.ps1 is not digitally signed. You cannot run this script on the current system.
    Cannot capture jmeter traffic in fiddler
    JMETER + POST + anti-forgery token
    input type color
    HearthBuddy修改系统时间
    What are all the possible values for HTTP “Content-Type” header?
    UDK性能优化
  • 原文地址:https://www.cnblogs.com/h-zhang/p/12215276.html
Copyright © 2011-2022 走看看