執行緒組
執行緒組作為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
秒,為什麼這次成功執行了呢?
持續時間
的設定,只作用於還未執行的取樣器。已經執行的取樣器,無論等待多長時間,都會執行完成。
本文示例介面原始碼可從前言中下載。