通過jmeter測試Java性能


通過jmeter測試Java性能

對java與scala等代碼或客戶端的性能測試,不能直接發起http請求,需要實例化對象發送請求實現性能測試。

  1. jmeter提供的Java Request取樣器可以控制實現JavaSamplerClient接口的類,輸入參數並獲取響應,利用多線程進行性能測試。
  2. 通過maven插件啟動jmeter,配合部分插件管理依賴,簡化每次測試環境的准備工作。

環境搭建

1. 搭建方式

手動配置環境:

  1. 創建測試項目
  2. 復制jmeter lib與lib\ext目錄下的依賴文件添加到當前工程,如eclipse:鼠標選中工程點擊右鍵 -> Build Path -> Configure Build Path -> 彈出框Libraries Tab -> 點擊 Add External JARs -> 切換到待導入路徑選取依賴jar
  3. 創建測試類實現JavaSamplerClient接口或繼承AbstractJavaSamplerClient,並重寫。 並不推薦使用實現接口的方式,使用集成AbstractJavaSamplerClient的方式比較好。
  4. 編譯源碼,導出為Runnable Jar File
  5. 編譯后jar包放入jmeter lib\ext目錄,項目依賴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() + "\tsetupTest()"); 
  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() + "\trunTest()" + "\tTime:\t" + 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. 編寫測試計划,單線程運行一下

測試代碼
測試代碼

測試結果
測試結果

多添加幾個線程的聚合報告
多添加幾個線程的聚合報告


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM