5. 堪比JMeter的.Net壓測工具 - Crank 實戰篇 - 接口以及場景壓測


1. 前言

通過之前的學習,我們已經掌握了crank的配置以及對應http基准工具bombardier、wrk、wrk2的用法,本篇文章介紹一下如何將其用於實戰,在實際的項目中我們如何使用crank來完成壓測任務。

2. 項目背景

目前有一個項目,我們希望通過壓測來了解其QPS、吞吐量、以及臨界值,並通過壓測來分析出其瓶頸在哪里?並通過解決瓶頸問題以提高QPS、吞吐量等指標

先看下我們手頭掌握了什么:

  • 項目信息
    • 項目中的接口基本都需要登錄
    • 通過與開發溝通可以得到每個頁面的接口信息以及參數信息
  • 環境信息
    • 壓測項目有單獨的環境部署應用、Redis、數據庫等基礎配置

此處項目名我們暫定為ProjectA。

3. 如何開展

首先我們先回顧一下Agent、Controller的職責以及特點

  • Controller
    • 做任務調度以及結果輸出
    • 無需單獨服務器,可以在本機執行發送命令,需要與Agent相通
  • Agent
    • 任務的實際執行者
    • 單任務執行,不能做到接收到多個任務並同時執行,先收到哪個任務,哪個任務會先執行
    • 相同一個任務可以被多個Agent同時執行,最終指標結果會自動累加,可以通過提升Agent來模擬更高的並發能力

3.1. 思路

  • 先做好單獨接口的壓測,大概掌握每個接口的指標情況
  • 同時壓測多個接口,完成對場景的壓測
  • 通過壓測觀察應用服務器、基礎服務器的CPU、帶寬、內存等指標,觀察Redis、數據庫、消息隊列等基礎組件情況,根據壓測的返回結果得到每個場景的基礎指標
  • 通過分析發現瓶頸、然后再考慮如何突破瓶頸,提升QPS、吞吐量等

3.2. 如何做?

了解到單個Agent同時執行多個任務會進行排隊,無法做到多任務同時執行,那么我們可以通過多個Agent同時執行不同的任務來模擬用戶訪問頁面。

3.2.1. 構建Agent

之前與開發溝通得到每個頁面最多可發送的請求是6個,那么我們准備6個Agent,分別為Agent1、Agent2、Agent3、Agent4、Agent5、Agent6

我們這里使用Docker來啟動Agent、Agent對內開放端口: 5010、對外端口隨機,鏡像使用我們自建的: doddgu/crankagent:net5.0

並新建load.yml為之后壓測使用:

profiles:
  crankAgent1:
    jobs:
      load:
        endpoints:
          - http://localhost:5010
  crankAgent2:
    jobs:
      load:
        endpoints:
          - http://localhost:5011
  crankAgent3:
    jobs:
      load:
        endpoints:
          - http://localhost:5012
  crankAgent4:
    jobs:
      load:
        endpoints:
          - http://localhost:5013
  crankAgent5:
    jobs:
      load:
        endpoints:
          - http://localhost:5014
  crankAgent6:
    jobs:
      load:
        endpoints:
          - http://localhost:5015

load.yml 中記錄了所有的壓測機信息,其信息一般不做修改,我們可以作為公共的配置來使用無需每個項目都單獨維護一份新的

3.2.2. 構建壓測腳本

在這里我們選擇wrk2作為本次基准測試工具,選擇wrk2的原因是:

  • 支持隨機參數
  • 可支持設置恆定的吞吐量負載
  • 具備wrk的所有功能

此時我們針對ProjectA項目新建配置:project.profiles.yml,作為本次壓測的環境配置來使用,其配置如下

imports:
  - https://raw.githubusercontent.com/doddgu/crank/sample/samples/wrk2/common/load.profiles.yml # 這邊建議使用遠程load.profiles.yml地址。(如果輸入的是本地路徑、則需輸入與當前命令所在路徑的相對路徑)

profiles:

  local: # 本地環境
    variables:
      serverAddress: localhost # 應用服務域
      serverPort: 80 # 應用服務端口
      connections: 256 # 每個線程處理時保持打開的 HTTP 連接總數 N = 連接數/線程數
      threads: 32 # 線程數
      warmup: 3 # 預熱時間: 3s
      duration: 180 # 測試時長: 3分鍾
      rate:  # 吞吐量參數(每秒總請求數)

project.profiles.yml中記錄了指定項目的各環境的配置,項目自己獨立維護即可

除了項目信息、壓測機配置之外,我們還需要有地方維護我們壓測的接口信息,這邊我的做法是將api獨立拆分出來,每個yml只配置一個接口的壓測信息,至於為什么不放到一塊,而要單獨拆分開呢?

這塊考慮到我們壓測的最小單元是API接口,如果把API接口獨立拆分開,那么可以對單接口壓測,而如果我們需要場景壓測,也可以通過組合接口完成多接口同時壓測,並且一旦我們完成了某個接口的壓測編寫,后續不需要再改動這個配置,如果我們按照場景拆分成不同的yml,在yml中再根據定義不同的scenario來做,那么后續場景新增加接口,還需要再更改這個場景的yml,並且scenario中的場景實際上也是根據接口維度區分的,目前crank並不能完成單個場景任務同時處理,基於以上原因,這邊我們新調整好的配置格式為:

新增load.benchmarks.yml

imports:
  - https://raw.githubusercontent.com/doddgu/crank/sample/src/Microsoft.Crank.Jobs.Wrk2/wrk2.yml
  - https://raw.githubusercontent.com/doddgu/crank/sample/samples/wrk2/common/project.profiles.yml

jobs:
  server:
    source:
      repository: https://github.com/doddgu/crank
      branchOrCommit: sample
      project: samples/hello/hello.csproj
    readyStateText: Application started.

scenarios:
  api:
    application: # 實際壓測項目時可移除此節點,此處是為模擬應用服務啟動
      job: server
      variables:
        duration: 1
    load:
      job: wrk2
      variables:
        serverPath: /user/get
        script: request.lua
        duration: 1

profiles:
  defaultParamLocal: # 本地環境的參數信息
    variables: 
      serverQueryString: ?id={1}
      serverQueryParameter: 1||2 # 隨機請求/get?id=1、/get?id=2

按照此格式保存,后續新增接口也可以快速復制,簡單修改即可快速完成壓測工作的編寫,這樣一來,如果我們希望對localhost:5000/user/get這個接口做壓測,僅需要在crank控制端輸入:

crank --config load.benchmarks.yml --scenario api --load.framework net5.0 --application.framework net5.0 --profile local --profile crankAgent1 --description "獲取用戶詳情" --profile defaultParamLocal

3.2.3. 構建批處理命令

但作為一個開發人員,總是希望事情能更簡單一點,每次輸入命令太麻煩了,所以就想到了通過批處理快速完成任務的發送,最終的項目結構就變成了

benchmarks
├─ defaultTitle              接口名稱( Description )
└─ load.bat                  最終執行的腳本,其中指定了要指定的yml配置、場景、以及任務環境是.net 5.0
└─ load.benchmarks.yml       yml配置
└─ load.local.bat            測試本地環境時要執行的腳本、格式:load.{環境}.bat
└─ README.md                 幫助文檔

每次通過雙擊load.{環境}.bat就完成了對當前接口的壓力測試,然后就是等待結果輸出……

| application           |                |
| --------------------- | -------------- |
| CPU Usage (%)         | 1              |
| Cores usage (%)       | 10             |
| Working Set (MB)      | 85             |
| Private Memory (MB)   | 278            |
| Build Time (ms)       | 3,469          |
| Start Time (ms)       | 352            |
| Published Size (KB)   | 93,323         |
| .NET Core SDK Version | 5.0.404        |
| ASP.NET Core Version  | 5.0.13+55738ff |
| .NET Runtime Version  | 5.0.13+b3afe99 |


| load                  |                |
| --------------------- | -------------- |
| Build Time (ms)       | 3,281          |
| Start Time (ms)       | 0              |
| Published Size (KB)   | 74,276         |
| .NET Core SDK Version | 5.0.404        |
| ASP.NET Core Version  | 5.0.13+55738ff |
| .NET Runtime Version  | 5.0.13+b3afe99 |
| First Request (ms)    | 86             |
| Requests/sec          | 2              |
| Requests              | 2              |
| Mean latency (ms)     | 2.68           |
| Max latency (ms)      | 2.68           |
| Bad responses         | 0              |
| Socket errors         | 0              |
| Latency 50th (ms)     | 2.68           |
| Latency 75th (ms)     | 2.68           |
| Latency 90th (ms)     | 2.68           |
| Latency 99th (ms)     | 2.68           |
| Latency 99.9th (ms)   | 2.68           |
| Latency 99.99th (ms)  | 2.68           |
| Latency 99.999th (ms) | 2.68           |

3.2.4. 構建場景壓測批處理命令

通過上面的一番操作,我們已經可以很容易的對單接口進行壓測,但目前想模擬完成多接口同時壓測,還需要再改造一下,之前我們想到,crank目前只能完成單獨壓測任務,那是不是有多個Agent,每個Agent單獨壓測一個接口,並同時啟動多個Agent同時壓測是不是可以模擬出來場景壓測,那我通過批處理任務多點幾次不同的接口壓測不就可以了,基於以上考慮,又做了一個批處理腳本,用於調用多個接口的壓測任務啟動,最后的結構如下所示:

Crank
├─ benchmarks                壓測腳本
│  ├─ api                   接口壓測腳本               
│  │  ├─ add               
│  │  └─ get                  
│  ├─ scipts               lua腳本             
│  │  ├─ common            lua公共腳本
│  │  │  ├─ oauth.lua     認證lua腳本
│  │  │  ├─ util.lua      lua工具類腳本
│  │  ├─ request.lua       封裝請求lua腳本   
│  ├─ scripts.tar           lua腳本壓縮包
├─ common                            
│  ├─ load.profiles.yml     agent 負載機配置
│  ├─ project.profiles.yml  項目配置
│  ├─ scripts.profiles      crank 執行script配置,用於對輸出結果的二次處理
│  ├─ project.profiles.yml  項目配置
├─ scripts                   場景壓測腳本
│  ├─ 用戶.bat              用戶壓測     
└─ env                       環境配置,標記當前需要壓測的環境在哪個配置文件中存儲
└─ env.local                 本地環境,存儲本地環境的配置信息
└─ README.md                 幫助文檔

4. 結尾

通過上面的操作我們已經完成了對單接口以及單場景的壓測,通過控制台可以清晰的看到每個接口的壓測結果,我們只需要耐心等待壓測任務結束,並整理壓測結果數據,最后進行匯總我們的任務就完成了,但壓測結果的收集也是一個費事費力的工作,作為一個開發,是不想把時間花費到這些整理表格的事情上,那我們如何做可以把整理表格數據的工作節省下來讓我們可以歇會兒呢……

源碼地址:https://github.com/doddgu/crank/tree/sample/samples/wrk2

參考鏈接:

開源地址

MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks

MASA.Contrib:https://github.com/masastack/MASA.Contrib

MASA.Utils:https://github.com/masastack/MASA.Utils

MASA.EShop:https://github.com/masalabs/MASA.EShop

MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor

如果你對我們的 MASA Framework 感興趣,無論是代碼貢獻、使用、提 Issue,歡迎聯系我們

16373211753064.png


免責聲明!

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



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