locust+geventhttpclient 性能優化


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

 

一、locust 自帶 httpclient 

locust 自帶 client 是 requests 庫的,這個庫功能很強大,也是最常用的,但性能很一般。

測試腳本:

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:625

 CPU 單核占用 100%

 

壓測場景二:

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

 CPU 8核 平均使用率 100%

 

二、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,json,os,sys,socket
from locust.exception import LocustError
from geventhttpclient import HTTPClient
from geventhttpclient.url import URL


host = 'http://10.1.62.133'
# 任務
class UserTsak(TaskSet):
    def on_start(self):
        '''初始化數據'''
        url = URL(host)
        # 若為https請求,ssl設置為True
        self.http = HTTPClient(url.host,url.port,ssl=False,connection_timeout=20,network_timeout=20)

    @task
    def test(self):
        try:
            start_time = time.time()
            # get 請求
            res = self.http.get("/sz/api2/test")
            # post 請求示例
            # body = json.dumps({"username":"admin","password":"123456"})
            # res = self.http.post("/sz/api2/login",body = body)
            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 socket.timeout:
            events.locust_error.fire(locust_instance=UserTsak, exception='Timeout', tb =sys.exc_info()[2])

        except Exception as e:
            events.locust_error.fire(locust_instance=UserTsak, exception='Error:{}。\nstatus_code:{}。\n接口返回:{}。'.format(e,res.status_code,data), tb=sys.exc_info()[2])

    def on_stop(self):
        '''運行結束,關閉http/https連接'''
        self.http.close()

class WebsiteUser(HttpLocust):
    host = host
    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 創建腳本很方便,各種統計、圖形報告很豐富,眾多插件支持,這個仁者見仁,智者見智哈。 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM