Locust 執行原理分析

yongheng999發表於2024-03-16
從指令碼中可以看出,指令碼主要包含兩個類,一個是 `UserLocust`(繼承自 `HttpLocust`,而 `HttpLocust`繼承自 `Locust`),另一個是 `UserCollects`(繼承自 `TaskSet`)。事實上,在 `Locust`的測試指令碼中,所有業務測試場景都是在 `Locust`和 `TaskSet`兩個類的繼承子類中進行描述的。

那如何理解 `Locust`和 `TaskSet`這兩個類呢?

簡單地說,`Locust類`就好比是一群蝗蟲,而每一隻蝗蟲就是一個類的例項。相應的,`TaskSet類`就好比是蝗蟲的大腦,控制著蝗蟲的具體行為,即實際業務場景測試對應的任務集。

接下來,我將分別對 `Locust`和 `TaskSet`兩個類進行詳細介紹。

**class HttpLocust(Locust)**

在 `Locust類`中,具有一個 `client`屬性,它對應著虛擬使用者作為客戶端所具備的請求能力,也就是我們常說的請求方法。通常情況下,我們不會直接使用 `Locust`類,因為其 `client`屬性沒有繫結任何方法。因此在使用 `Locust`時,需要先繼承 `Locust類`,然後在繼承子類中的 `client`屬性中繫結客戶端的實現類。

對於常見的 `HTTP(S)`協議,`Locust`已經實現了 `HttpLocust`類,其 `client`屬性繫結了 `HttpSession`類,而 `HttpSession`又繼承自 `requests.Session`。因此在測試 `HTTP(S)`的 `Locust指令碼`中,我們可以透過 `client`屬性來使用 `Python requests`庫的所有方法,包括 `GET/POST/HEAD/PUT/DELETE/PATCH`等,呼叫方式也與 `requests`完全一致。另外,由於 `requests.Session`的使用,因此 `client`的方法呼叫之間就自動具有了狀態記憶的功能。常見的場景就是,在登入系統後可以維持登入狀態的 `Session`,從而後續HTTP請求操作都能帶上登入態。

而對於 `HTTP(S)`以外的協議,我們同樣可以使用 `Locust`進行測試,只是需要我們自行實現客戶端。在客戶端的具體實現上,可透過註冊事件的方式,在請求成功時觸發 `events.request_success`,在請求失敗時觸發 `events.request_failure`即可。然後建立一個繼承自 `Locust類`的類,對其設定一個 `client`屬性並與我們實現的客戶端進行繫結。後續,我們就可以像使用 `HttpLocust類`一樣,測試其它協議型別的系統。

原理就是這樣簡單!

在 `Locust類`中,除了 `client`屬性,還有幾個屬性需要關注下:

* `task_set`: 指向一個 `TaskSet`類,`TaskSet`類定義了使用者的任務資訊,該屬性為必填;
* `max_wait/min_wait`: 每個使用者執行兩個任務間隔時間的上下限(毫秒),具體數值在上下限中隨機取值,若不指定則預設間隔時間固定為1秒;
* `host`:被測系統的host,當在終端中啟動 `locust`時沒有指定 `--host`引數時才會用到;
* `weight`:同時執行多個 `Locust類`時會用到,用於控制不同型別任務的執行權重。

測試開始後,每個虛擬使用者(`Locust例項`)的執行邏輯都會遵循如下規律:

1. 先執行 `userCollects`中的 `on_start`(只執行一次),作為初始化;
2. 從 `userCollects`中隨機挑選(如果定義了任務間的權重關係,那麼就是按照權重關係隨機挑選)一個任務執行;
3. 根據 `Locust類`中 `min_wait`和 `max_wait`定義的間隔時間範圍(如果 `TaskSet類`中也定義了 `min_wait`或者 `max_wait`,以 `TaskSet`中的優先),在時間範圍中隨機取一個值,休眠等待;
4. 重複 `2~3`步驟,直至測試任務終止。

**class TaskSet**

再說下 `TaskSet類`。

效能測試工具要模擬使用者的業務操作,就需要透過指令碼模擬使用者的行為。在前面的比喻中說到,`TaskSet類`好比蝗蟲的大腦,控制著蝗蟲的具體行為。

具體地,`TaskSet類`實現了虛擬使用者所執行任務的排程演算法,包括規劃任務執行順序(`schedule_task`)、挑選下一個任務(`execute_next_task`)、執行任務(`execute_task`)、休眠等待(`wait`)、中斷控制(`interrupt`)等等。在此基礎上,我們就可以在 `TaskSet`子類中採用非常簡潔的方式來描述虛擬使用者的業務測試場景,對虛擬使用者的所有行為(任務)進行組織和描述,並可以對不同任務的權重進行配置。

相關文章