locust+geventhttpclient 性能優化

  上一篇講述了 Locust 的單進程,多進程,分佈式的使用,在壓測的時候發現客戶機 cpu 基本接近100%,當服務器資源還很空閒,客戶機已先達到瓶頸了。下文使用同一臺客戶機(8核8g)壓測網關,對比優化前和優化後的效果。git

 

1、locust 自帶 httpclient 

locust 自帶 client 是 requests 庫的,這個庫功能很強大,也是最經常使用的,但性能很通常。github

測試腳本:json

from locust import HttpLocust, TaskSet, task, between # 任務
class UserTsak(TaskSet): def on_start(self): '''初始化數據'''
        pass @task def test(self): self.client.get("/sz/api2/test") def on_stop(self): '''銷燬數據'''
        pass

class WebsiteUser(HttpLocust): host = 'https://10.1.62.133' task_set = UserTsak wait_time = between(0, 0)

壓測場景一:

1個進程,100 個 user。平均 qps:625api

 CPU 單核佔用 100%服務器

 

壓測場景二:

 8個進程,100 個 user。平均 qps:4847併發

 CPU 8核 平均使用率 100%分佈式

 

2、locust + geventhttpclient

    geventhttpclient  GitHub 地址:https://github.com/locustio/geventhttpclient 高併發

1)geventhttpclient 中的 httpclient 使用協程實現,性能相對 requests 庫提高5~6倍。而後使用 events(事件)從新定義客戶端,events(事件)最終會把壓測中產生的數據輸出到 UI 界面。做爲壓測腳本,咱們要儘量減小沒必要要的邏輯。工具

from locust import HttpLocust, TaskSet, task, between, events import time from locust.exception import LocustError from geventhttpclient import HTTPClient from geventhttpclient.url import URL # 任務
class UserTsak(TaskSet): def on_start(self): '''初始化數據''' url = URL('http://10.1.62.133') self.http = HTTPClient(url.host) @task def test(self): try: start_time = time.time() res = self.http.get("/sz/api2/test") data = res.read() end_time = time.time() response_time =int((end_time - start_time)*1000) response_length = len(data) assert json.loads(data)['Error'] == 0 if res.status_code == 200: events.request_success.fire(request_type="GET", name="test_success", response_time = response_time, response_length=response_length)

        except AssertionError: end_time = time.time() response_time =int((end_time - start_time)*1000) events.request_failure.fire(request_type="GET", name="test_failure", response_time=response_time,response_length=0, exception="斷言錯誤。status_code:{}。接口返回:{}。".format(res.status_code,json.loads(data))) except Exception as e: events.locust_error.fire(locust_instance=UserTsak, exception=e, tb =sys.exc_info()[2]) def on_stop(self): '''運行結束,關閉http/https鏈接''' self.http.close() class WebsiteUser(HttpLocust): host = 'http://10.1.62.133' task_set = UserTsak wait_time = between(0, 0)

 

2)其實還有一種簡單的實現方式,官網上有案例,代碼和 locust+requests 同樣。須要安裝geventhttpclient,而後將 WebsiteUser 繼承的超類換成 FastHttpLocust類 便可。但實際測試下來不如 案例1 來的高效(差異還蠻大的),緣由多是 events(事件)處理不如自定義效率高。性能

from locust import TaskSet, task, between from locust.contrib.fasthttp import FastHttpLocust # 任務
class UserTsak(TaskSet): def on_start(self): '''初始化數據'''
        pass @task def test(self): self.client.get("/sz/api2/test") def on_stop(self): '''銷燬數據'''
        pass

class WebsiteUser(FastHttpLocust): host = 'https://10.1.62.133' task_set = UserTsak wait_time = between(0, 0)

 

 壓測場景一:

 1個進程,100 個 user。平均 qps:3948

  CPU 單核佔用也接近 100%,看起來是單進程客戶端瓶頸了

 

壓測場景二:

8個進程,100 個 user。平均 qps:9424

 CPU 8核平均使用率 60% 左右

 

總結一下:

        經過下面表格能夠看出,locust + geventhttpclient 性能提高幅度仍是挺大的,單進程提高5倍多,開8個slave後 CPU佔用在60%。

 httpclient方式 單進程qps CPU使用率(單進程模式) 多進程qps(8個進程) CPU使用率 (多進程模式)
locust + requests  625 100%(單核)  4847  100%(平均)
locust + geventhttpclient  3948 100%(單核)  9424  60%(平均)

 

 

 

 

       

  如下是用 jmeter 在同一臺客戶機100線程壓測結果,平均qps在9000左右,比 locust 稍低。並且 locust 在高併發能力方面比 jmeter 強多了,因此推薦使用 locust 做爲壓測工具。固然 jmeter 的優點也不少,好比:使用 GUI 建立腳本很方便,各類統計、圖形報告很豐富,衆多插件支持,這個仁者見仁,智者見智哈。 

 

相關文章
相關標籤/搜索