[譯]性能測試最佳實踐之JMeter

原文地址: JMeter best-practices

保持使用最新版本

JMeter被經常推薦用來測試性能,鼓勵用戶使用最新的版本。

確保你要經常去閱讀變更記錄中的新功能和模塊的提升。你不應該再使用3.0之前的版本了

使用正確的線程數

你硬件設備的能力及測試計劃將都會影響你的JMeter可運行的線程數。數量也依賴于你的服務有多快(一個可快速響應的服務可以讓JMeter變更更加給力)。像其它性能測試工具一樣,如果你沒有正確的線程數,你將面對不準備或錯誤結果的Coordinated Omission問題。如果你需要大數量級的壓力測試,考慮使用分布式模式在多臺機器上運行無GUI的JMeter實例。當使用分布式模式時,結果將被聚合在控制器的結果中,如果使用多個自已的實例,結果文件可以聚合用于持續性分析。對于如何在一個給定的平臺上使用JMeter測試,JavaTest Sampler可以考慮使用。它不需要任何網絡請求便可返回一些信息在最大的吞吐量。

JMeter有選項用于延遲線程創建直到線程正常啟動,如在其它線程組延遲之后和線程自身的啟動時間。這樣就允許一個非常大數量級的線程數,不需要太多的線程同時并發。

Cookie管理器的位置

可在構建一個Web測試中查看

Authorization管理器的位置

可在構建一個高級Web測試中查看

使用HTTP(S) Test Script Recorder錄制

關于HTTP(S) Test Script Recorder的細節在建議錄制器中。最重要的事情是,剔除你不感興趣的。比如,不關心在錄制過程中的圖片請求(JMeter可以下載一個頁面中的所有圖片-具體查看HTTP Request)。這些內容將會讓你的測試計劃一團糟糕。大部人都會這樣,有一個擴展對你的所有文件集,如.jsp,.asp,.php,.html或者其它。這些內容你通過輸入.*\.jspInclude Pattern引入

或者,你也可以剔除圖片通過輸入.*\.gifExclude Pattern中。具體依據你的應用程序,你可以選擇一種更好的方案去執行。你也可以去剔除stylesheets,javascritpt文件和其它文件類型。測試你的配制來驗證你的錄入內容是你想要的,接著清除內容并且開始刷新頁面。

HTTP(S) Test Script Recorder期望用于使用Recording Controller發現HTTP Request記錄的元素至一個線程組元素中。這樣便于你可以直接將所有的樣例打包至一個控制器下,當然可以再給出一個可描述測試用例的名稱。

現在,執行測試用例的步驟。如果你有無前置步驟的測試用例,使用JMeter來錄制你的操作定義你的測試用例。一旦你完成了一系列特定的操作,保存整個測試用例至一個合適的文件名中。接著,清理記錄開始一個新的測試用例。通過這樣操作,你可以快速記錄大量粗糙的測試用例。

HTTP(S) Test Script Recorder最有用的一個特性是你可以通過錄制的樣例來抽象出通用的元素。通過定義自定義的用戶變量在測試計劃級別或在用戶自定義變量元素中,你可以用JMeter自動替換你錄制樣例中的值。比如,如果你測試一個APP在服務xxx.example.com,你可以定義一個變量server的值為xxx.example.com,再所有在錄制樣例中的值將會被替換為${server}

匹配時,注意大小寫敏感

如果JMeter沒有錄制到任何請求,檢查你的瀏覽器是否啟用代理設置。如果在JMeter沒有啟動時,瀏覽器可正常使用,那瀏覽器一定是沒有使用代理設置。一些瀏覽器忽略了代理設置localhost127.0.0.1,那么請使用本機名或IP代替。

錯誤unknown_ca可以是你正試圖錄入HTTPS,瀏覽器不接收JMeter的代理服務證書。

用戶變量

一些測試計劃中,需要使用不同的值對于不同的用戶/線程。如,你想測試需要每個用戶登錄后的一系列步驟。這個使用JMeter可以很容易實現。

比如:

  • 創建一個文件,包含用戶名和密碼且使用逗號分隔。存放到與你的測試計劃在同一文件夾。
  • 添加一個CSV DataSet的配制元素至你的測試計劃。定義變量名為USERPASS
  • 替換登錄名為${USER}和密碼為${PASS}

CSV DataSet元素將會為每個線程讀取一新行內容。

減少資源使用

減少資源使用的一些建議:

  • 使用無GUI的模式: jmeter -n -t test.jmx -l test.jtl
  • 盡量少使用監聽器Listener;如果使用上面的-l標記,他們均可以被刪除或禁用
  • 在壓力測試過程中,不要使用查看結果樹在Table中查看結果監聽器,僅在腳本調試階段使用即可
  • 相比使用大量相似的樣例,在一個循環中使用相同的樣例,并使用變量(CSV DataSet)來實現樣例的不同。[Include Controller在此步驟沒有任何用,它在文件中添加所有的測試元素至測試計劃中]
  • 不要使用功能模式
  • 使用CSV格式輸出要優于XML
  • 僅保存需要的數據
  • 盡可能使用少的斷言
  • 使用最優的腳本語言(查看JSR223部分)

如果你的測試需要大量的數據 - 特別是如果需要隨機化的 - 創建測試數據在可被讀取的CSV文件中。這樣會避免浪費資源在運行時。

BeanShell服務

BeanShell解釋器有一個很有用的特性 - 當可以用來扮演server,可被telnethttp訪問。

沒有安全性。能連接至端口的任何人都可以發布任何BeanShell命令。這些可以提供無限制的訪問至JMeter程序和目標。
不要啟用服務除非端口被限制訪問,如,被防火墻。

如果你想使用服務,在jmeter.properties中定義下面內容:

beanshell.server.port=9000
beanshell.server.file=../extras/startup.bsh

在上面的例子中,服務將會被啟動,將會監聽端口90009001。端口9000用于http訪問,端口9001用于telnet訪問。startup.bsh文件將會被服務處理,可被用于定義功能和啟動時的變量。啟動文件定義用于啟動和輸出JMter和系統屬性的方法。這些是你將在JMeter控制臺看到的:

Startup script running
Startup script completed
Session started on port: 9001

有一個樣例腳本(extras/remote.bsh)你可以用來測試服務。[看看它怎么工作的]

當啟動當在JMeterbin目錄(調整目錄,如果你在其它位置),輸出會像這樣:

$ java -jar ../lib/bshclient.jar localhost 9000 ../extras/remote.bsh
Connecting to BSH server on localhost:9000
Reading responses from server …
BeanShell 2.0b5 - by Pat Niemeyer (pat@pat.net)
bsh % remote.bsh starting
user.home = C:\Documents and Settings\User
user.dir = D:\eclipseworkspaces\main\JMeter_trunk\bin
log_level.jmeter = INFO
log_level.jorphan = INFO
Setting property 'EXAMPLE' to '0'.
Setting property 'EXAMPLE' to '1'.
Setting property 'EXAMPLE' to '2'.
Setting property 'EXAMPLE' to '3'.
Setting property 'EXAMPLE' to '4'.
Setting property 'EXAMPLE' to '5'.
Setting property 'EXAMPLE' to '6'.
Setting property 'EXAMPLE' to '7'.
Setting property 'EXAMPLE' to '8'.
Setting property 'EXAMPLE' to '9'.
EXAMPLE = 9
remote.bsh ended
bsh % … disconnected from server.

舉個例子,假設你有一個運行時間較長的非GUI運行模式測試,并且你想讓吞吐量在測試過程中不同。測試計劃包括Constant Throughout Timer定義屬性,如${__P(thoughput)}。下面的BeanShell可用于改變測試:

printprop("throughput");
curr = Integer.decode(args[0]);  // Start value
inc  = Integer.decode(args[1]);  // Increment
end  = Integer.decode(args[2]);  // Final value
secs = Integer.decode(args[3]);  // Wait between changes
while(curr <= end) {
  setprop("throughput",curr.toString()); // Needs to be a string here
  Thread.sleep(secs*1000);
  curr += inc;
}
printprop("throughput");

腳本可以被存儲在一個文件中(如,throughput.bsh),使用bshclient.jar發送至服務。參考:

java -jar ../lib/bshclient.jar localhost 9000 throughput.bsh 70 5 100 60

BeanShell腳本

概述

每一個BeanShell測試元素在解釋器中的每個線程中均有自己的副本。如果測試元素被重復調用,如: 在loop中,那么元素會被解釋器存儲在報文中除非Reset bsh.Interpreter before each call選項被勾選。對擴展的壓力測試,推薦使用腳本引擎集成了可編譯的JSR223腳本語言,可在JSR223中查看詳情。

一些運行時間較長的測試會導致解釋器使用大量的內存;如果真的要這樣做,嘗試使用reset選項。

你可以測試BeanShell腳本使用命令行解釋器,不依賴于JMeter:

$ java -cp bsh-xxx.jar[;other jars as needed] bsh.Interpreter file.bsh [parameters]

$ java -cp bsh-xxx.jar bsh.Interpreter
bsh% source("file.bsh");
bsh% exit(); // or use EOF key (e.g. ^Z or ^D)

共享變量

變量可以被定義在啟動(安裝)腳本。這些數據將會被存儲在測試元素的報文中,除非你使用reset選項。

腳本也可以讀取JMeter的變量通過使用get()put()方法,如:

vars.get("HOST");
vars.put("MSG","Successful");

get()put()方法僅支持字符串變量,但有getObject()putObject()方法可以處理其它類型。JMeter變量對于線程是局部的,但可以被所有的測試元素使用(不適用于BeanShell)。

如果你需要共享變量在線程間,JMeter的屬性可以使用:

import org.apache.jmeter.util.JMeterUtils;
String value = JMeterUtils.getPropDefault("name","");
JMeterUtils.setProperty("name", "value");

樣例.bshrc文件包括樣例getprop()setprop()的方法定義。

其它可用于共享變量的方法,使用bsh.shared共享命名空間。參考:

if (bsh.shared.myObj == void){
    // not yet defined, so create it:
    myObj = new AnyObject();
}
bsh.shared.myObj.process();

相比在測試元素中創建對象,可通過JMeter的屬性beanshell.init.file文件配制在啟動時創建。這個僅會執行一次。

使用BeanShell Javascript Jexl腳本開發功能

像功能一樣編寫和測試腳本是很困難的。然而,JMeter有JSR223BSFBeanShell可用來嘗試。

創建一個簡單的測試計劃包括JSR223BSF樣例和結果樹監聽器。在樣例板塊編寫腳本,通過運行測試來測試它。如果有很多錯誤,這些結果將會被展示在結果樹中。同時運行腳本的結果將會被展示像返回內容一樣。

一旦腳本調試通過,可以當一個變量被存儲在測試計劃中。腳本的變量可被用于創建功能調用。如,支持一個BeanShell腳本被存儲在變量RANDOM_NAME。功能調用可以被編寫為${__BeanShell($RANDOM_NAME)}。不需要其它的逗號在腳本中,因為在變量值被添加之前,功能調用已經被轉化。

參數化測試

經常對于重復運行一個測試在不同的配制中是很有用的。比如,改變線程數/循環數/改變地址名。

一種方式是在測試計劃中定義變量集,并在測試元素中使用這些變量。比如,一個可以定義變量LOOPS=10,關聯${LOOPS}至線程組中。為了運行測試循環20次,只需要調整LOOPS在測試計劃中的值。

這個會快變得糟糕,如果你想在非GUI模式運行的話。一個解決方案是,定義測試計劃變量在屬性中,如LOOPS=${__P(loop,10)}。這個使用屬性loops的值,如果沒找到的話默認為10loops屬性也可被JMeter的控制臺命令定義:

jmeter ... -Jloops=12 ...

如果有大量的屬性在一次變更的話,一種實現方式是使用屬性文件屬性文件可通過使用-q在命令行模式下傳遞至JMeter。

JSR223元素

為了擴展壓力測試,推薦的腳本語言是一種腳本引擎實現可編譯接口的腳本語言。Groovy腳本引擎可編譯。然而,在JMeter 2.13版本無論是BeanShell還是Javascript都沒有實現,因此最好不要使用它們來擴展壓力測試。

提醒: BeanShell繼承可編譯接口但還沒有被實現,方法會拋異常。JMeter有一個明確的說明關于這個問題。

當使用JSR223元素時,經常設置存儲一個值至一個唯一的變量中,如果語言支持它。確保腳本沒有使用變量${varName}來存儲將會獲取第一個值,將會獲取${varName}的第一個值。替換使用:

vars.get("varName")

你也可以傳遞他們像參數一樣到腳本中,并且像這樣使用它們。

線程組之間共享變量

變量對于線程是局部的;在一個線程中的一個變量集不能被其它線程讀取。設計就是這樣的。針對變量,可以在測試啟動前進行明確,查看參考化測試。如果值直到測試啟動都不知道,有如下選項:

  • 存儲變量在屬性中 - 屬性對于JMter實例是全局的
  • 寫變量至文件中,重新讀取他們
  • 使用bsh.shared命令空間 - 查看共享變量
  • 寫自己的Java類

屬性配制管理

當你需要修改JMeter屬性,確保你沒有修改jmeter.properties文件。替換拷貝屬性從jmter.properties并修改在user.properties中的值。
這樣做的話,會很容易合并至下一個JMeter版本。
注意jmeter.properties文件中經常涉及但被理解“從jmeter.properties拷貝到user.properties你想修改且這樣做的屬性。”

user.properties file supersedes the properties defined in jmeter.properties

過時的元素

建議不要使用過時的元素(被這樣標記在變更記錄和在組件相關),并且合并使用新的元素如果可用的話,或新的方式可以實現相同的事情。
過時的元素被刪除從菜單在版本N中,但通過修改user.propertiesnot_in_menu中屬性可被啟用,并且從那刪除完整的類名。

請注意過濾時的元素地版本`N`將會被刪除在確定的版本`N+1`中,因此盡早確保你沒有使用。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,013評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,146評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,534評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,767評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,318評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,074評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,258評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,486評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,993評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,234評論 2 375

推薦閱讀更多精彩內容