?
線程組
?
線程組作為JMeter測試計劃的核心組件之一,對于模擬并發用戶的行為至關重要。線程組元件是整個測試計劃的入口,所有的取樣器和控制器必須放置在線程組下。
可以將線程組視為一個虛擬用戶池,其中每個線程可被理解為一個虛擬用戶,多個虛擬用戶同時執行相同的一批任務。
在這個虛擬用戶池中,每個線程之間是相互隔離且互不影響的。每個線程的執行過程中,操作的變量不會對其他線程的變量值產生影響。
線程組的關鍵任務之一是定義并發用戶的行為,包括設置線程數、循環次數、啟動延遲等關鍵參數。通過適當配置線程組,測試人員可以模擬多用戶在系統中同時執行任務的場景,從而評估系統的性能和穩定性。
通過靈活使用setup線程組、線程組、tearDown線程組、開放模型線程組,配置前置操作、主要操作、后置操作,更能真實、詳細的評估系統。
線程組分為四類:
- 線程組
- setUp線程組
- tearDown線程組
- 開放模型線程組
線程組、setUp線程組、tearDown線程組控制面板中的元素基本一致:
- 名稱、注釋
- 在取樣器錯誤后執行的動作
- 線程數
- Ramp-Up時間
- Same user on each iteration
- 延遲創建線程直到需要(只有線程組有)
- 調度器
開放模型線程組控制面板中的元素:
- 名稱、注釋
- 在取樣器錯誤后執行的動作
- 調度計劃
- 隨機種子
取樣器錯誤后執行的動作
在JMeter中,取樣器(Sampler)是用于模擬用戶請求發送到目標服務器的組件,例如HTTP請求、FTP請求等。當取樣器執行過程中出現錯誤時,可以通過配置相應的動作來處理這些錯誤。以下是一些處理取樣器錯誤時,線程組中常見方式:
-
停止線程
任何一個線程(用戶)在執行過程中遇到錯誤時,該線程被停止,不影響其他線程(用戶)。
-
啟動下一進程循環
任何一個線程(用戶)在執行過程中遇到錯誤時,Jmeter會立即停止當前線程的本次執行,并進行當前線程(用戶)的下次執行,主要應用于線程多次循環時。 -
繼續(無需演示)
JMeter將在取樣器執行錯誤時,忽略錯誤繼續執行本線程的后續操作及執行其他線程。
停止線程-多線程
示例接口代碼
@ThreadGroup.route('/api/ThreadGroup5/', methods=['GET', 'POST'])
def threadgroup5(): return '200'
示例Jmeter腳本
-
測試計劃下添加線程組
取樣器錯誤后執行的動作
中勾選停止線程
線程數
:3
-
線程組下依次添加2個HTTP 請求取樣器
名稱:
錯誤請求-${yonghu}
(在前)、正確請求-${yonghu}
請求地址:
HTTP://127.0.0.1:5000/api/ThreadGroup5/
請求方式:
GET
-
線程組下添加CSV 數據文件設置(右鍵-添加-配置元件)
文件名
:ceshi.txt的路徑
?ceshi.txt文件內容:(復制后,手動刪除前面的空格)
??200,用戶1
??1111,用戶2
??200,用戶3
文件編碼
:UTF-8
變量名稱
:ceshi,yonghu
-
錯誤請求取樣器下添加響應斷言
值:
${ceshi}
-
在測試計劃中,添加查看結果樹
運行結果
連續運行了3次,結果是一致的。總共有三個用戶執行線程組,其中用戶1
、用戶3
完全執行成功;用戶2
只執行了錯誤請求
。
因為設置取樣器錯誤后執行的動作
為停止線程
,用戶2
執行錯誤請求
時發生錯誤,Jmeter只會停止用戶2
的后續執行,不會影響其他線程。
多線程組也是多線程,讀者在實際的腳本編寫中,要注意每個線程的情況去使用停止線程
。
停止線程-多循環
示例接口代碼
@ThreadGroup.route('/api/ThreadGroup5/', methods=['GET', 'POST'])
def threadgroup5(): return '200'
示例Jmeter腳本
-
測試計劃下添加線程組
取樣器錯誤后執行的動作
中勾選停止線程
循環次數
:3
-
線程組下依次添加2個HTTP 請求取樣器
名稱:
錯誤請求-${xunhuan}
(在前)、正確請求-${xunhuan}
請求地址:
HTTP://127.0.0.1:5000/api/ThreadGroup5/
請求方式:
GET
-
線程組下添加CSV 數據文件設置(右鍵-添加-配置元件)
文件名
:ceshi.txt的路徑
?ceshi.txt文件內容:(復制后,手動刪除前面的空格)
??200,第1次循環
??1111,第2次循環
??200,第3次循環
文件編碼
:UTF-8
變量名稱
:ceshi,xunhuan
-
錯誤請求取樣器下添加響應斷言
值:
${ceshi}
-
在測試計劃中,添加查看結果樹
運行結果
連續運行了3次,結果是一致的。用戶在第2次循環執行到錯誤請求
時,Jmeter停止測試。
因為設置取樣器錯誤后執行的動作
為停止線程
,用戶的第2次循環,執行錯誤請求
時發生錯誤,Jmeter停止用戶的后續執行(就它一個線程)。
啟動下一進程循環
示例接口代碼
@ThreadGroup.route('/api/ThreadGroup5/', methods=['GET', 'POST'])
def threadgroup5(): return '200'
示例Jmeter腳本
-
測試計劃下添加線程組
取樣器錯誤后執行的動作
中勾選啟動下一線程循環
循環次數
:3
-
線程組下依次添加2個HTTP 請求取樣器
名稱:
錯誤請求-${xunhuan}
(在前)、正確請求-${xunhuan}
請求地址:
HTTP://127.0.0.1:5000/api/ThreadGroup5/
請求方式:
GET
-
線程組下添加CSV 數據文件設置(右鍵-添加-配置元件)
文件名
:ceshi.txt的路徑
?ceshi.txt文件內容:(復制后,手動刪除前面的空格)
??200,第1次循環
??1111,第2次循環
??200,第3次循環
文件編碼
:UTF-8
變量名稱
:ceshi,xunhuan
-
錯誤請求取樣器下添加響應斷言
值:
${ceshi}
-
在測試計劃中,添加查看結果樹
運行結果
連續運行了3次,結果是一致的。用戶執行了3次循環,其中第2次循環中,錯誤請求
出現錯誤,跳過正確請求
。
因為設置取樣器錯誤后執行的動作
為啟動下一線程循環
,用戶的第2次循環,執行錯誤請求
時發生錯誤,Jmeter會跳過用戶的本次執行,進行用戶的后續執行。
ramp-up時間
ramp-up時間用于設置啟動所有線程所需要的時間。例如:線程數設置為10,ramp-up時間設置為100秒,那么JMeter將使用100秒使10個用戶啟動并運行,即每個用戶將在前一個用戶啟動后的10秒啟動。
如果ramp-up值設置得很小、線程數又設置得很大,剛開始執行測試時會對服務器產生很大的壓力。
示例接口代碼
@ThreadGroup.route('/api/ThreadGroup5/', methods=['GET', 'POST'])
def threadgroup5(): return '200'
示例Jmeter腳本
-
測試計劃下添加線程組
Ramp-Up時間
:9線程數
:3
-
線程組下添加1個HTTP 請求取樣器
請求地址:
HTTP://127.0.0.1:5000/api/ThreadGroup5/
請求方式:
GET
-
在測試計劃中,添加查看結果樹
運行結果
連續運行了3次,結果是一致的。3
個用戶執行線程組
,各個用戶的請求時間分別為2024-04-15 16:12:37 CST
、2024-04-15 16:12:40 CST
、2024-04-15 16:12:43 CST
。
3
個用戶執行請求的間隔時間正好是3
秒,即ramp-up時間/線程數
。
same user on each iteration(在每次迭代中使用相同的用戶)
沒有研究出來它有什么用。經過我的測試,same user on each iteration(在每次迭代中使用相同的用戶)
啟用與否,作用是一樣的。
如讀者對此有不同見解,歡迎與我聯系,共同探討。目前,我十分費解。
延遲創建線程直到需要
當在JMeter中啟用延遲創建線程直到需要
時,JMeter會根據預設的Ramp-up時間
動態地分配線程。假設Ramp-up時間
設置為20秒,線程數
為10,那么JMeter會在測試啟動后立即創建第一個線程并開始請求處理。隨后,每隔2秒,JMeter將創建下一個線程,直到所有線程都被啟動。
如果關閉“延遲創建線程直到需要”選項,JMeter會在測試開始時一次性創建所有線程。使用同樣的參數,即在測試一開始,JMeter會立即創建全部的10個線程。這些線程會按照設定的“Ramp-up時間”進行執行,每個線程將間隔2秒啟動。
延遲創建線程直到需要
這一配置的目的是為了應對測試機性能有限的情況。通過這種方式,可以避免在測試初期就創建所有線程,導致資源過度占用和可能的性能問題。這種方法有助于平滑地增加系統負載,同時防止資源瞬間緊張導致測試無法正常進行。
調度器-啟動延遲
調度器
主要控制線程操作時間。啟用調度器
后,可以輸入持續時間
(值不能為空),啟動延遲
來控制線程組的操作時間及線程組操作前的延遲時間。
同時輸入持續時間
,啟動延遲
時,先計算啟動延遲
,再計算持續時間
。
示例接口代碼
@ThreadGroup.route('/api/ThreadGroup5/', methods=['GET', 'POST'])
def threadgroup5(): return '200'
示例Jmeter腳本
-
測試計劃下添加線程組
啟用
調度器
持續時間
:10啟動延遲
:3
-
線程組下添加1個HTTP 請求取樣器
請求地址:
HTTP://127.0.0.1:5000/api/ThreadGroup5/
請求方式:
GET
-
在測試計劃中,添加查看結果樹
運行結果
注意看圖中右上角-黃色三角形左邊的計時器
,值固定在2
秒。這個計時器計算整個測試計劃的持續時間。由于示例請求的接口響應較快,可以理解為計時器的時間就是HTTP請求
時的時間。
因為啟動延遲
設置為3
秒,所以HTTP請求
會在延遲3
秒執行。不過計時器的時間是2
秒,誤差1
秒。我多次試過把持續時間
、啟動延遲
的時間拉長,誤差還是1
秒。
調度器-持續時間
調度器
主要控制線程操作時間。啟用調度器
后,可以輸入持續時間
(值不能為空),啟動延遲
來控制線程組的操作時間及線程組操作前的延遲時間。
同時輸入持續時間
,啟動延遲
時,先計算啟動延遲
,再計算持續時間
。
示例接口代碼
@ThreadGroup.route('/api/ThreadGroup6/', methods=['GET', 'POST'])
def threadgroup6(): sleep(3) return '200'
示例Jmeter腳本
-
測試計劃下添加線程組
啟用
調度器
持續時間
:2 -
線程組下添加1個HTTP 請求取樣器
請求地址:
HTTP://127.0.0.1:5000/api/ThreadGroup6/
請求方式:
GET
-
HTTP 請求下添加1個固定定時器
值:
3000
-
在測試計劃中,添加查看結果樹
運行結果
圖中結果樹中什么都沒有,這是因為線程組的持續時間
只有2
秒,但固定定時器
的延遲有3
秒,導致還未執行取樣器
,持續時間已經結束。
此時刪掉固定定時器,運行結果
此時有人會有疑問。接口中設置的休眠時間
就已經是3
秒了,腳本中的持續時間
還只是2
秒,為什么這次成功執行了呢?
持續時間
的設置,只作用于還未執行的取樣器。已經執行的取樣器,無論等待多長時間,都會執行完成。
?