線程組,是說到 JMeter 會第一時間想到的東西,也是我認為 JMeter 最難理解的知識點。因為項目讓你做個壓測,首先就是要考慮並發,用 JMeter 就是用多線程 來模擬多並發。但在看到線程組編輯區的時候,選項密密麻麻,無從下手呀。本篇文章就給大家介紹 JMeter 線程組的玩法。
JMeter 為什么能做性能測試
我們雖然都知道 JMeter 使用線程在模擬用戶,但是它到底是怎么模擬真實場景的?為什么它就能做性能測試?
為了解答這些疑惑,我們從最簡單的登錄壓測講起。假設新項目要上線了,需要做個壓測,看看 100 個人同時登陸系統,性能怎么樣。
我們先不用 JMeter,先用人工來做。找 100 個人,讓這些人把自己的賬號密碼輸好后,叫一聲,登錄!他們就一起點擊登錄按鈕。
這樣就算性能測試了么?不算。而且這樣測的結果並沒有參考意義。就算我們算出了此時登錄接口響應時間是 0.5 s,那么這 0.5 s 也不能作為 100 個人同時登陸的響應時間。學過統計學就知道,單個樣本數據是會有偏差的,在實驗中需要測量多次后取平均值,才能減少誤差。
然后我們用 JMeter 來做。設置 100 個線程,模擬 100 個用戶,持續 5 分鍾,讓這 100 個線程不停的登錄,產生成千上萬條並發請求。假如登錄比較慢或登錄失敗了,用戶肯定會不停的點,就會造成持續不斷的請求。JMeter 的線程也可以設置無限迭代來模擬這一情況。
測試結束后,再對所有的大量的樣本數據,進行性能分析,得出平均響應時間、TPS、吞吐量等性能指標,以評估當前配置下系統性能情況,找到性能瓶頸,為性能優化提供依據。
這就是 JMeter 能做性能測試的原因,也是性能測試的意義。
知道了為什么,接下來講講怎么做。如果設置不當,有可能 100 個線程只能產生 1 個並發請求。
JMeter 的線程組編輯區如下:

Name
名稱,最好有業務意義。
Comments
注釋,可以為空。
Action to be taken after a Sampler error
線程組中某個線程的請求出錯后,該怎么處理。有 5 個選項,Continue,Start Next Thread Loop,Stop Thread,Stop Test,Stop Test Now。
例如,假設有 1 個線程,包括 2 個取樣器,迭代執行 2 次:

Continue
請求出錯后,線程繼續運行。
為什么要繼續運行呢?我們在大量用戶並發時,服務器偶爾響應錯誤是正常現象,比如服務器由於性能問題 500,此時出錯我們正好要記錄下來,作為有性能問題的依據。但是仍然可以繼續請求進行重試,說不定服務器又能訪問了,這樣可以算出錯誤率。
比如,登錄失敗了,那么下單的操作由於登錄失敗,也會跟着失敗。
默認選擇此項,保證足夠的並發壓力。
Start Next Thread Loop
如果出錯,則同一線程中的余下請求將不再執行,直接重新開始新一輪迭代。
比如,登錄失敗了,那么下單的操作將不再執行,重新開始。
如果想減少關聯請求報錯,可以選擇此項。
Stop Thread
一般不會設置此項,它指的是請求失敗后,停止當前線程,不再執行。這樣會導致運行線程越來越少,最后負載不夠,對服務器的壓力不夠,測試結果不具參考性。
Stop Test
如果某一線程的某一請求失敗了,停止所有線程測試。
但是每個線程還是會執行完當前迭代后再停止。相當於 Continue 到當前迭代結束。
比如線程 1 正好執行到登錄,有其他線程出錯了,線程 1 也會執行完下單操作才會停止。
Stop Test Now
如果有線程的請求失敗了,立即停止所有線程,不再執行。
Thread Properties
Number of Threads (users)
運行的線程數設置,一個線程對應一個模擬用戶。
Ramp-up period (seconds)
所有線程在多長時間內開始運行,單位是秒。
比如我們設置線程數為 50,此處設置 10 秒,那么每秒就會啟動 50 / 10,5 個線程。如果設置為 0 秒,則 50 個線程會立刻啟動。如果設置為 100 秒,就會每隔 100 / 50, 2 秒 啟動 1 個線程。
Ramp-up period的大小問題
Ramp-up period的大小問題,對於初學者來說是最容易困擾的。
以下是 5 個線程依次從啟動到執行退出的示意圖:

紅色框起來的部分才是真正 5 個線程並發請求的時間段。
假設我們設置 20 個線程,只運行 1 次迭代,看看不同的啟動時間設置會有結果有何不同。
如果啟動時間設置為 0,那么測試一開始就會產生 20 個並發請求,服務器萬一只能承受 15 個並發,豈不是一上來就 gg 了,還測個什么呀。
如果啟動時間設置為 40,那么會每隔 2 秒 啟動 1 個線程。萬一線程執行不到 1 秒就退出了,第 2 個線程 啟動的時候,第 1 個線程已經退出了,不就是只產生了 1 個並發請求么。
那么設置成多少合適呢?我也不知道,但是結合我查閱的資料,可以給出一個參考意見。
第一步,把線程組跑 1 次(可以在線程組元件上右鍵選擇 Validate),從聚合報告獲取到吞吐量(Throughput)。
第二步,用線程數量除以吞吐量,得出啟動時間。
例如,200 個線程,跑一次獲取到吞吐量為 4/sec,啟動時間為 200 / 4 = 50。這樣設置以后,第 2 個線程啟動后,剛好第 1 個線程執行完開始新的迭代,從而形成梯度遞增的並發請求。
Loop Count
迭代次數。可以填寫數字指定迭代次數。也可以勾選 Infinite,表示無限迭代,一直運行到測試停止或異常崩潰。
Same user on each iteration
在 JMeter 中,user 就是線程,此選項的意思是說每個迭代都用相同的線程。
這個得從老版本講起,在以前 3.x 和 4.x 版本的 JMeter 中,是沒有這個選項的。創建好 1 個線程后,每次迭代都是用這個線程,直到測試結束。它的影響就是,比如登錄,加了 HTTP Cookie 管理器以后,單個線程多次迭代(注意不是多個線程哦)登錄用的都是相同的 Cookie。
5.x 版本加入了這個選項,可以控制每次迭代是否創建新的線程。同時在 HTTP Cookie 管理器也增加了一個選項,控制是否清除舊 Cookie:

默認這個 Same user on each iteration 的選項是勾選的。因為銷毀和創建線程本身就會占用資源,可能會影響性能測試結果。
Delay Thread creation until needed
跟 JVM 創建線程時機有關,實際運用勾不勾選都不影響測試結果,保持默認就好。
Specify Thread lifetime
Duration
持續時間,單位秒。Loop Count 勾選了 Infinite,才有作用。
Startup delay
啟動延遲,單位秒。延遲到時間后再運行線程。
簡單回顧
本文首先解析了 JMeter 為什么能做性能測試的原因,接着對線程組編輯區的選擇進行了講解,重點梳理了Ramp-up period的大小問題。此外,JMeter Plugins 還提供了兩個線程組元件 Ultimate Thread Group 與 Stepping Thread Group,以滿足浪涌(波濤狀,多個波峰)的場景。筆者水平有限,若有錯誤,請指正。
參考資料:1.《全棧性能測試修煉寶典JMeter實戰》
