使用JMeter進(jìn)行性能測(cè)試 —“Java請(qǐng)求”方式

JMeter是Apache組織的開放源代碼項(xiàng)目,它是功能和性能測(cè)試的工具,100%的用java實(shí)現(xiàn),最新的版本是2.9,大家可以到官網(wǎng)下載源代碼和查看相關(guān)文檔。之前本科的時(shí)候,SQA課程作業(yè)中我們組使用過2.4版本,這次更新了2.9感覺最直觀的就是界面上有了小的更改,增加了清除、啟動(dòng)等按鈕。

關(guān)于使用JMeter進(jìn)行JDBC數(shù)據(jù)庫測(cè)試、HTTP請(qǐng)求接口測(cè)試、結(jié)合Badboy錄制功能進(jìn)行網(wǎng)站性能測(cè)試等內(nèi)容,網(wǎng)上的資料比較豐富,這里就暫時(shí)不做介紹了。更實(shí)用和靈活的場(chǎng)景,是實(shí)用我們自己編寫的jar包進(jìn)行測(cè)試,這也就是“Java請(qǐng)求”方式的測(cè)試。這里主要記錄一下我在學(xué)習(xí)這種測(cè)試方式時(shí)遇到的一些問題,和總體流程,算作一個(gè)記錄和小總結(jié)。

1. JMeter安裝

準(zhǔn)確的來說,我認(rèn)為JMeter是不需要安裝的,下載好JMeter Binary版本后,在本地解壓縮,進(jìn)入bin文件夾,執(zhí)行ApacheJMeter.jar文件即可。這里提供一個(gè)觀望的2.9版本的下載鏈接,時(shí)間久了可能會(huì)失效,這個(gè)時(shí)候可以進(jìn)入Apache JMeter項(xiàng)目主頁再選擇download頁面。

image.png

打開JMeter程序后,我們可以看到JMeter的主界面,是下圖的這個(gè)樣子(2.9版本)。

image.png

2. 使用JMeter創(chuàng)建測(cè)試計(jì)劃

如果我們希望實(shí)用JMeter進(jìn)行性能測(cè)試,則首先需要?jiǎng)?chuàng)建一個(gè)測(cè)試計(jì)劃,我們可以對(duì)測(cè)試計(jì)劃進(jìn)行保存,這樣當(dāng)我們下一次需要再次執(zhí)行這個(gè)測(cè)試的時(shí)候,只需要打開已保存的測(cè)試計(jì)劃文件(.jmx文件)就可以執(zhí)行了,無需再次創(chuàng)建。

1)點(diǎn)擊“測(cè)試計(jì)劃”,在右側(cè)輸入框中可以修改測(cè)試計(jì)劃的名稱,并添加注釋,這里我偷個(gè)懶就不改了,使用默認(rèn)的。

2)為測(cè)試計(jì)劃添加一組Threads,選擇線程組。這組Threads就相當(dāng)于是一組用戶,每個(gè)顯示代表一個(gè)用戶執(zhí)行相關(guān)操作。

image.png
  1. 編輯線程組屬性。設(shè)置響應(yīng)內(nèi)容,比較重要的是線程數(shù)、ramp-up period和循環(huán)次數(shù)。這里設(shè)置線程數(shù)為1、ramp-up period為1和循環(huán)次數(shù)1,即線程組中只有1個(gè)線程,這個(gè)線程在計(jì)劃啟動(dòng)后1秒就開始執(zhí)行,只執(zhí)行1次。
image.png

圖上的ramp-up period解釋不正確,這個(gè)屬性表示每個(gè)用戶(線程)啟動(dòng)的遲延時(shí)間。例如,如果你輸入Ramp-Up Period 為5秒,JMeter將會(huì)在五秒結(jié)束前完成啟動(dòng)所有的用戶。所以,如果你有五個(gè)用戶并且Ramp-Up Period為5秒,那么開始用戶的延遲就是1秒。(5個(gè)用戶/5秒=1用戶每秒)。如果你設(shè)置的Ramp-Up Period為0,則JMeter將會(huì)立即啟動(dòng)你所有的用戶。

如果勾選了“調(diào)度器”,則可以定時(shí)啟動(dòng)線程。

image.png

4)為線程組添加Sampler取樣器,取樣器表明這組線程執(zhí)行測(cè)試的類型,即發(fā)送請(qǐng)求的類型、怎樣發(fā)送請(qǐng)求的。我們這里選擇“Java請(qǐng)求”,表明這組線程是通過某個(gè)Java類發(fā)送請(qǐng)求的。


image.png

5)編輯“Java請(qǐng)求”屬性。下圖這個(gè)大家可以發(fā)現(xiàn)已經(jīng)有了Launcher類,和userName、password、authUrl的值了,這是因?yàn)椋?. 我之前寫了滿足一定要求的代碼,打了jar包,放入了JMeter的lib/ext文件夾下了,所以可以看到Launcher;2. 我在Launcher類中的getDefaultParameters方法中添加了默認(rèn)的userName、password、authUrl值。這里的“滿足一定要求”請(qǐng)繼續(xù)參閱下文。

image.png

6)為Java請(qǐng)求添加監(jiān)聽器,選擇“聚合報(bào)表”和“圖形結(jié)果”,這樣在啟動(dòng)測(cè)試后,我們就可以獲得測(cè)試結(jié)果的數(shù)據(jù),分別以報(bào)表和圖形的結(jié)果展示。


image.png

image.png

7)點(diǎn)擊啟動(dòng)(菜單欄中的綠色三角形按鈕)。測(cè)試完成可以看到測(cè)試結(jié)果。為了結(jié)果好看一點(diǎn),我把線程數(shù)改成了10,循環(huán)改成了100 :P


image.png

image.png

這里對(duì)測(cè)試結(jié)果中的幾個(gè)指標(biāo)進(jìn)行說明:

樣本數(shù)目 總共發(fā)送到服務(wù)器的請(qǐng)求數(shù)。
最新樣本 代表時(shí)間的數(shù)字,是服務(wù)器響應(yīng)最后一個(gè)請(qǐng)求的時(shí)間。
吞吐量 服務(wù)器每分鐘處理的請(qǐng)求數(shù)。
平均值 是總運(yùn)行時(shí)間除以發(fā)送到服務(wù)器的請(qǐng)求數(shù),即每個(gè)請(qǐng)求的平均響應(yīng)時(shí)間。
中間值 是代表時(shí)間的數(shù)字,有一半的服務(wù)器響應(yīng)時(shí)間低于該值而另一半高于該值。
偏離 表示服務(wù)器響應(yīng)時(shí)間變化、離散程度測(cè)量值的大小,即數(shù)據(jù)的分布。
90%line 90%的響應(yīng)時(shí)間都比這個(gè)時(shí)間小
Min 代表時(shí)間的數(shù)字,是服務(wù)器響應(yīng)的最短時(shí)間。
Max 代表時(shí)間的數(shù)字,是服務(wù)器響應(yīng)的最長時(shí)間。
Error% 請(qǐng)求的錯(cuò)誤百分比。
KB/sec 是每秒鐘請(qǐng)求的字節(jié)數(shù)。

3. 實(shí)現(xiàn)“Java請(qǐng)求”代碼

針對(duì)"Java請(qǐng)求"類型的測(cè)試,需要基于JMeter測(cè)試框架編寫測(cè)試用例。

1)新建一個(gè)普通的Java工程

2)添加JMeter的包引用,這些包位于 JMeter安裝目錄/lib/ext下,一般只需要ApacheJMeter_core.jar和ApacheJMeter_java.jar這兩個(gè)。

3)新建一個(gè)Java Class,如下例中的“Launcher”,并繼承“AbstractJavaSamplerClient”。AbstractJavaSamplerClient中默認(rèn)實(shí)現(xiàn)了四個(gè)可以覆蓋的方法,分別是“getDefaultParameters”,“setupTest”,“runTest”和“teardownTest”方法。

  • getDefaultParameters 方法主要用于設(shè)置傳入界面的參數(shù);

  • setupTest方法為初始化方法,用于初始化性能測(cè)試時(shí)的每個(gè)線程;

  • runTest方法為性能測(cè)試時(shí)的線程運(yùn)行體;

  • teardownTest方法為測(cè)試結(jié)束方法,用于結(jié)束性能測(cè)試中的每個(gè)線程。

package cn.edu.zju.swift.test;
?
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
?
import cn.edu.zju.swift.JtangSwiftClient;
import cn.edu.zju.swift.model.result.AccountResult;
?
public class Launcher extends AbstractJavaSamplerClient{

 private JtangSwiftClient client;

 @Override
 /**
 * JMeter界面中展示出此方法所設(shè)置的默認(rèn)參數(shù)。
 * @return
 */
 public Arguments getDefaultParameters() {

 Arguments args = new Arguments();

 args.addArgument("authUrl", "http://192.168.3.51:8080/auth/v1.0");
 args.addArgument("userName", "test:tester");
 args.addArgument("password", "testing");

 return args;
 }
?
 /** 
 * 執(zhí)行runTest()方法前會(huì)調(diào)用此方法,可放一些初始化代碼 
 */ 
 @Override
 public void setupTest(JavaSamplerContext context) {

 // 創(chuàng)建SwiftClient
 this.client = new JtangSwiftClient(15000, 15000, 8192, true, false);
 }
?
 /** 
 * 執(zhí)行runTest()方法后會(huì)調(diào)用此方法,可放一些資源釋放代碼
 */ 
 @Override
 public void teardownTest(JavaSamplerContext context) {

 // 關(guān)閉連接
 this.client.close();
 }
?
 @Override
 /**
 * 性能測(cè)試時(shí)的線程運(yùn)行體,執(zhí)行的業(yè)務(wù)方法放在這里。
 */
 public SampleResult runTest(JavaSamplerContext context) {

 // 創(chuàng)建SampleResult對(duì)象,用于記錄執(zhí)行結(jié)果的狀態(tài),并返回
 SampleResult sampleResult = new SampleResult();
?

 // 獲取JMeter中輸入的用戶參數(shù)
 String authUrl = context.getParameter("authUrl");
 String userName = context.getParameter("userName");
 String password = context.getParameter("password");

 // 開始
 sampleResult.sampleStart();

 AccountResult accountResult = client.auth(authUrl, userName, password);
?
 // 暫停
 // sampleResult.samplePause();

 // 重啟
 // sampleResult.sampleResume();

 // 結(jié)束
 sampleResult.sampleEnd();

 sampleResult.setSuccessful(accountResult.isSuccess());

 // 返回
 return sampleResult;
 }
}

4)代碼編寫完畢后,把上面的例子打包(使用eclipse右鍵項(xiàng)目 -> export -> jar,即可)。然后把生成的"swift-random-action-test.jar"文件拷貝到JMeter的安裝目錄lib\ext下,就可以在上述2. 使用JMeter創(chuàng)建測(cè)試計(jì)劃”的4)Java請(qǐng)求編輯頁面的下拉列表中看到Launcher類了。**

這里有兩點(diǎn)需要注意

1. 如果你的jar依賴了其他第三方j(luò)ar,需要將其一起放到lib/ext下,否則會(huì)出現(xiàn)ClassNotFound錯(cuò)誤,這個(gè)問題也是困擾了我好久的 T^T;

2. 如果在將jar放入lib/ext后,你還是無法找到你編寫的類,且此時(shí)你是開著JMeter的,則需要重啟一下JMeter。

以上就是使用JMeter的Java請(qǐng)求方式進(jìn)行一個(gè)測(cè)試計(jì)劃構(gòu)建的全過程了,都是比較基礎(chǔ)的方法,如果需要什么額外的功能還可以慢慢學(xué)習(xí)。雖然自己也有寫多線程并發(fā)的客戶端測(cè)試代碼,并自己收集response time等,計(jì)算TPS,但顯然使用JMeter的方式更加方便,因?yàn)槟阒恍枰凑諉尉€程的方式去實(shí)現(xiàn)你的測(cè)試業(yè)務(wù),也無需添加各種埋點(diǎn)收集數(shù)據(jù)。

綜上,感覺JMeter還是很強(qiáng)大的,最近打算多學(xué)習(xí)一點(diǎn),對(duì)以后寫代碼,自我測(cè)試性能也是很有幫助的,再配合jProfiler的使用,可以很好的保證Java代碼的效率和性能。當(dāng)然,工具只能“錦上添花”,最根本的還是需要我們自己可以編寫出高質(zhì)量的代碼啦 :D

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容