1. 程式人生 > >[搬運工系列]-jmeter(一)工具介紹(二)

[搬運工系列]-jmeter(一)工具介紹(二)

1.Jmeter 概要描敘

jmeter 是一款專門用於功能測試和壓力測試的輕量級測試開發平臺。多數情況下是用作壓力測試,該測試工具在阿里巴巴有著廣泛的使用,估計是不要錢吧,哈哈,功能上來說,整個平臺實現了許多和網際網路相關的網路測試元件,同時還保留著很強的擴充套件性方便用於一些非標準的測試場景,讓偉大的程式猿同學來告訴它該如何工作。下面我們開始。

 

2.Jmeter 基本介面和元件的概念

 

 

 

現在看到了Jmeter的主介面。下面介紹Jmeter中主要元件的功能和作用, 首先我們看看Jmeter在概念上的元件分類如圖

1.Threads:這個元件主要用來控制Jmeter併發時產生執行緒的數量,在它的下一級選單下只有一個元件(執行緒組),可以這麼理解每個執行緒就是一個虛擬的使用者。所有的其他型別元件必須是(執行緒組)節點的子節點。

2.配置單元:和Sample元件一起工作,主要用來配置Sample如何來發起請求訪問伺服器,這個東西的主要特點是可以把一些Sample的共同配置放在一個元素裡面方便管理,配置單元是有作用域的。作用域和樹的那個關係一樣越是上級節點的作用域越大,越是接近葉子節點的

作用域就越小,可以複寫上級作用域的配置。

3.定時器 : 這個主要是用來調節(執行緒組),控制執行緒每次執行測試邏輯(比如說:發出請求)的時間間隔。當然這個下面還有很多型別的定時器,他們主要功能就是調節時間間隔,但個個元件之間的策略有很大不同。

4.前置處理器 和 後置處理器類似一個HOOK,在測試執行之前和執行之後執行一些指令碼的邏輯。該元件我還沒有具體使用過,但大致功能就是這樣,非重點元件。

5.Sample : 可能上圖中沒有出現Sample,需要在(ThreadGroup)上新增才可以,見圖

 

 

Sample表示客戶端傳送某種格式或者規範的請求到服務端,所以大家看到了各種各樣的Sample,其中有兩個Http 相關的。一般用HttpClient功能和效率將更強。

6.斷言: 意思是指對於Sample完成了請求傳送之後,判斷一下返回的結果是否滿足期望。

7.監聽器 : 這個元件不同於平時在Web程式設計的那種監聽器,他是伴隨著Jemeter測試的執行而從中抓取執行期間的資料的一個元件,經常使用的是聚合報告元件,從裡面可以統計到測試的TPS,響應時間等關鍵測試資料。

 

3.例項操作

首先在TestPlan下面新增一個ThreadGroup元件,設定執行緒組元件各項引數

關鍵引數解釋 :

執行緒數:最大測試時使用的執行緒數。

Ramp-Up Period : Jmeter達到指定最大執行緒數的時間。

迴圈次數 : 如果是Forever,執行緒組中的執行緒將不間斷的連續測試系統,當然也可以設定每個執行緒測試的次數,當完成了規定次數後,該執行緒將自動退出執行緒組。

排程器 : 主要用來指定該測試的一些時間資訊,比如從幾點到幾點執行測試,如果到了指定時間測試沒有進行完成,測試也會被停止。

 

接著線上程組下面新增Sample元件,我們新增一個HTTP Request HTTPClient元件,設定屬性如下圖:

最後新增監聽器元件 :Aggregate Report, 大功告成!

執行:

 

好了,一個簡單的壓力測試例子完成了。大家可以從report中間看到一些效能結果的引數了。下面我們完成一個更復雜的例子。

 

4.自定義Sample或者協議完成測試

問題:在某些場景下我們會發現Jmeter裡面提供的各種Sample不能滿足自己的需求,應為這個世界上的壓力測試的邏輯本來就是千變萬化的,所以這個時候我們如果自己實現一套測試邏輯,這個時候需要使用jmeter 的擴充套件性。下面我們通過一個簡單的例子來看看如何開發這樣的一個自定義Sample? 自定Sample的生命週期是怎樣的?

 

[java]  view plain copy  
  1. package com.alibaba.stress.load;
  2. import org.apache.jmeter.config.Arguments;
  3. import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
  4. import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
  5. import org.apache.jmeter.samplers.SampleResult;
  6. public class LifecycleJMeterSampleextends AbstractJavaSamplerClient {
  7. @Override
  8. public Arguments getDefaultParameters() {
  9. System.out.println("Get Parameter name! [getDefaultParameters]");
  10. return super.getDefaultParameters();
  11. }
  12. @Override
  13. public void setupTest(JavaSamplerContext context) {
  14. System.out.println("[setupTest]");
  15. super.setupTest(context);
  16. }
  17. @Override
  18. public void teardownTest(JavaSamplerContext context) {
  19. System.out.println("[teardownTest]");
  20. super.teardownTest(context);
  21. }
  22. @Override
  23. public SampleResult runTest(JavaSamplerContext ctx) {
  24. SampleResult result = new SampleResult();
  25. result.sampleStart();
  26. System.out.println("[runTest]");
  27. result.setSuccessful(true);
  28. result.sampleEnd();
  29. return result;
  30. }
  31. }
[java]  view plain copy  
  1. package com.alibaba.stress.load;  
  2. import org.apache.jmeter.config.Arguments;  
  3. import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;  
  4. import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;  
  5. import org.apache.jmeter.samplers.SampleResult;  
  6. public class LifecycleJMeterSample extends AbstractJavaSamplerClient {  
  7.       
  8.       
  9.       
  10.       
  11.     @Override  
  12.     public Arguments getDefaultParameters() {  
  13.         System.out.println("Get Parameter name! [getDefaultParameters]");  
  14.         return super.getDefaultParameters();  
  15.     }  
  16.     @Override  
  17.     public void setupTest(JavaSamplerContext context) {  
  18.         System.out.println("[setupTest]");  
  19.         super.setupTest(context);  
  20.     }  
  21.     @Override  
  22.     public void teardownTest(JavaSamplerContext context) {  
  23.         System.out.println("[teardownTest]");  
  24.         super.teardownTest(context);  
  25.     }  
  26.     @Override  
  27.     public SampleResult runTest(JavaSamplerContext ctx) {  
  28.         SampleResult result = new SampleResult();  
  29.         result.sampleStart();  
  30.         System.out.println("[runTest]");  
  31.         result.setSuccessful(true);  
  32.         result.sampleEnd();  
  33.         return result;  
  34.     }  
  35. }  
[java]  view plain  copy  
  1. package com.alibaba.stress.load;  
  2. import org.apache.jmeter.config.Arguments;  
  3. import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;  
  4. import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;  
  5. import org.apache.jmeter.samplers.SampleResult;  
  6. public class LifecycleJMeterSample extends AbstractJavaSamplerClient {  
  7.       
  8.       
  9.       
  10.       
  11.     @Override  
  12.     public Arguments getDefaultParameters() {  
  13.         System.out.println("Get Parameter name! [getDefaultParameters]");  
  14.         return super.getDefaultParameters();  
  15.     }  
  16.     @Override  
  17.     public void setupTest(JavaSamplerContext context) {  
  18.         System.out.println("[setupTest]");  
  19.         super.setupTest(context);  
  20.     }  
  21.     @Override  
  22.     public void teardownTest(JavaSamplerContext context) {  
  23.         System.out.println("[teardownTest]");  
  24.         super.teardownTest(context);  
  25.     }  
  26.     @Override  
  27.     public SampleResult runTest(JavaSamplerContext ctx) {  
  28.         SampleResult result = new SampleResult();  
  29.         result.sampleStart();  
  30.         System.out.println("[runTest]");  
  31.         result.setSuccessful(true);  
  32.         result.sampleEnd();  
  33.         return result;  
  34.     }  
  35. }  

 

 

 

 

其中AbstractJavaSamplerClient是從ApacheJmeter_Java.jar 中獲得。編寫的類檔案打包xxx.jar, 把這個Jar放到Jmeter的解壓目錄下的lib/ext下。重新啟動jmeter.

 

一次先加入執行緒組,和聚合報告兩個元件,在聚合報告元件之前加入一個新的Sample(Java Sample ), 如圖:

 

執行測試。可以看到控制檯的輸出。調整幾次執行緒組的執行緒數目的控制,我們會發現我們的這個自定義類中的teardowntest 和 setupuptest方法都是正對執行緒組中的某一個執行緒來執行的,執行緒組中執行緒的呼叫數目其實就是指runtest方法的執行次數。

 

5.Jmeter的分散式測試(優缺點)

下面是分散式測試的使用方法,即使用一臺機器控制多臺機器給目標機器產生壓力。由於Linux和Windows上的方法有些不一樣,這裡說下Linux下是怎麼來配置的。

首先總控的機器我們叫master,產生壓力的肉雞我們叫JmeterServer,待我們測試的系統我們叫Target.

第一步:啟動JmeterServer。我們可以找到Jmeter/bin 目錄下的jmeter-server這個指令碼,執行即可,當然如果你需要調整這個測試負載產生伺服器的記憶體等效能引數的話,我們修改這個指令碼jmeter中的記憶體引數。

第二步 : 修改Master機器上jmeter/bin目錄下的jmeter.properties檔案,修改remote_hosts=localhost:1099,localhost:2010這個為你自己的JmeterServer的實際IP,如果有多臺可以用逗號分開。

第三步 : 啟動master jmeter,執行測試指令碼的時候選:執行 --> 遠端執行 --> 選擇IP 或者 執行所有遠端。JmeterServer就會執行Master機器上設定的執行指令碼了。

 

問題 : 我在實際使用中發現使用這種模式下的Jmeter在Master觀測實際測試結果,發現TPS遠遠低於使用傳統的一臺Jmeter來測試所能達到的TPS,我感覺可能是由於Jmeter這種多機器協作中傳遞資訊是使用RMI技術,可能這種技術本身還對Jmeter的效能產生了影響導致壓力上去的很慢。該問題還沒有得到完全認證,所以我現在如果在一臺機器測試產生的壓力不夠的情況下我直接使用多臺機器測把TPS加起來就是結果,比較傻,期待大俠指點迷津。