堪比JMeter的.Net壓測(cè)工具 - Crank 入門(mén)篇

1. 前言

Crank 是.NET 團(tuán)隊(duì)用來(lái)運(yùn)行基準(zhǔn)測(cè)試的基準(zhǔn)測(cè)試基礎(chǔ)架構(gòu),包括(但不限于)來(lái)自TechEmpower Web 框架基準(zhǔn)測(cè)試的場(chǎng)景,是2021年.NET Conf 大會(huì)上介紹的一項(xiàng)新的項(xiàng)目,其前身是Benchmarks。

Crank目標(biāo)之一是為開(kāi)發(fā)人員提供一種工具,讓他們能夠非常輕松地處理性能并衡量潛在的改進(jìn)。其中一些功能是:

  • 部署和基準(zhǔn)測(cè)試基于 .NET 或 Docker 容器的多層應(yīng)用程序

通過(guò)指定.Net項(xiàng)目(本地路徑或git遠(yuǎn)程倉(cāng)庫(kù)地址),支持直接部署或通過(guò)Docker部署應(yīng)用程序,用于基準(zhǔn)測(cè)試)

  • 通過(guò)Yml配置,不僅僅支持結(jié)果存儲(chǔ)在 JSON 、SQL Server 中還支持存儲(chǔ)到csv文件中以用于圖表

目前有小伙伴已經(jīng)在提議將支持存儲(chǔ)在es

  • 支持更改自定義應(yīng)用程序的Franework環(huán)境,測(cè)試在不同環(huán)境下的性能
  • 收集診斷跟蹤信息

2. 核心組成

Crank由Agent、Controller兩部分組成

Controller是任務(wù)的調(diào)度者,可以調(diào)度負(fù)載任務(wù)以及輸出結(jié)果

Agent是基準(zhǔn)代理,任務(wù)的實(shí)際執(zhí)行者,接收來(lái)自Controller的任務(wù)并執(zhí)行。

3. 安裝

欲先工其善 必先利其器,我們先學(xué)習(xí)下如何安裝crank,以及如何驗(yàn)證是否安裝成功

3.1. 準(zhǔn)備工作

  1. 安裝 .NET 5.0.

  2. 打開(kāi)shell:安裝Crank Controller

安裝命令:

dotnet tool update Microsoft.Crank.Controller --version "0.2.0-alpha.21567.1" --global

驗(yàn)證命令:

crank
  1. 打開(kāi)shell: 安裝Crank Agent

安裝命令:

dotnet tool update Microsoft.Crank.Agent --version "0.2.0-alpha.21567.1" --global

驗(yàn)證命令:

crank-agent

3.2. 小結(jié)

為方便閱讀、文章中Crank Controller簡(jiǎn)稱(chēng)Crank,Crank Agent簡(jiǎn)稱(chēng)Agent

Agent以及Crank需要根據(jù)實(shí)際情況安裝,可分以下幾種情況:

  • 只是為了學(xué)習(xí)Crank,沒(méi)有單獨(dú)的測(cè)試環(huán)境,則需要分別安裝Agent、Controller

  • Agent有單獨(dú)提供測(cè)試環(huán)境,則本地不需要安裝Agent,只安裝Controller即可

  • Agent有單獨(dú)提供測(cè)試環(huán)境,且壓測(cè)任務(wù)由ci來(lái)觸發(fā)執(zhí)行,則本地不需要安裝任何配置,通過(guò)構(gòu)建ci任務(wù)完成壓力計(jì)劃即可

打開(kāi)shell:查看Agent、Controller版本

dotnet tool list -g

4. 基礎(chǔ)知識(shí)

4.1. variables: 參數(shù)

variables分為局部參數(shù)與全局參數(shù)兩種類(lèi)型,在根節(jié)點(diǎn)的為全局參數(shù),在其他節(jié)點(diǎn)下的是局部參數(shù)。

例:

hello.benchmarks.yml > scenarios > hello-load > variables節(jié)點(diǎn)下的serverPort以及path以及profiles>local>variables節(jié)點(diǎn)下的serverAddress是局部參數(shù)

scenarios:
  hello:
    application:
      job: server
    load:
      job: bombardier
      variables:
        serverPort: 5000
        path: /

profiles:
  local:
    variables:
      serverAddress: localhost

bombardier.yml > variables > headers為全局參數(shù)

variables:
  headers:
    none: ''
    plaintext: '--header "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"'
    html: '--header "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" --header "Connection: keep-alive"'
    json: '--header "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"'
    connectionclose: '--header "Connection: close"'
    ---------------------------------------------------------------------

4.2. profiles: 配置

profiles其實(shí)就是配置文件信息,profiles允許被多次使用,這點(diǎn)在可以在文檔中找到對(duì)應(yīng)介紹

Usage: crank [options]

Options:
  -?|-h|--help                       Show help information

  These options are not specific to a Job

  ----------------------------------------------------------------------
  --profile <profile>                Profiles to apply. Can be used multiple times.

命名規(guī)則: 建議 *.profiles.yml

4.3. jobs: 任務(wù)

將我們要做的事定義為一個(gè)job。方便之后重用。此處的事指的是一類(lèi)事,而不是指特定的某件事。

例如:微軟內(nèi)置定義的bombardier就是一個(gè)job,這個(gè)job是通過(guò)bombardier對(duì)其進(jìn)行基準(zhǔn)測(cè)試,并將結(jié)果記錄并輸出,而具體針對(duì)哪個(gè)接口進(jìn)行基準(zhǔn)測(cè)試其實(shí)并不關(guān)心。

job根據(jù)應(yīng)用程序源有分為遠(yuǎn)程、本地兩種。

本地源:

jobs:
  server: #任務(wù)名稱(chēng),可根據(jù)任務(wù)作用自行命名
    source: #任務(wù)源
      localFolder: ../hello 
      project: hello.csproj #要構(gòu)建的 .NET 項(xiàng)目的文件名
    readyStateText: Application started. #控制臺(tái)中通知服務(wù)器它已啟動(dòng)的文本

本地源localFolder針對(duì)當(dāng)前運(yùn)行crank --config執(zhí)行命令所在的相對(duì)路徑即可,任務(wù)開(kāi)始后會(huì)將本地的項(xiàng)目發(fā)送到agent后再執(zhí)行任務(wù)。

遠(yuǎn)程源

jobs:
  server:
    source:
      repository: https://github.com/dotnet/crank
      branchOrCommit: main #遠(yuǎn)程源執(zhí)行任務(wù)的分支
      project: samples/hello/hello.csproj #要構(gòu)建的 .NET 項(xiàng)目的文件名,格式:相對(duì)根的相對(duì)路徑+項(xiàng)目名.csproj
    readyStateText: Application started.

遠(yuǎn)程源會(huì)將倉(cāng)庫(kù)信息發(fā)送到Agent,Agent會(huì)先將倉(cāng)庫(kù)下載下來(lái)并切換到指定的分支后再執(zhí)行構(gòu)建任務(wù)啟動(dòng)項(xiàng)目

4.4. scenarios: 場(chǎng)景

job關(guān)心的是一類(lèi)事,而特定的事情并不關(guān)心,那具體的事是誰(shuí)比較關(guān)心呢,沒(méi)錯(cuò)那就是場(chǎng)景,也就是scenarios,scenarios通過(guò)多個(gè)job來(lái)完成對(duì)指定場(chǎng)景的基準(zhǔn)測(cè)試,做的是具體任務(wù)的編排

4.5. imports: 導(dǎo)入

imports為我們提供了yml重用的可能,因?yàn)橛衖mports的支持,我們才可以將公共的yml提取到一個(gè)單獨(dú)的yml中,通過(guò)imports將使用到的yml導(dǎo)入即可,與js、css的導(dǎo)入有異曲同工之妙

4.6. 小結(jié)

在crank中,variables、profiles都不是必須的,但因?yàn)樗鼈兊拇嬖?,才使得我們可以以面向?qū)ο蟮乃枷腴_(kāi)發(fā),可以通過(guò)新增變量或指定配置完成基準(zhǔn)測(cè)試,這塊后面的實(shí)戰(zhàn)中會(huì)有詳細(xì)解釋

5. 入門(mén)

經(jīng)過(guò)之前的學(xué)習(xí),我們對(duì)crank的基本配置也有了一定的了解,那接下來(lái)的時(shí)間,我們先試著學(xué)習(xí)下官方已經(jīng)給我們準(zhǔn)備好的Sample,下面的教程也會(huì)詳細(xì)講解一下各個(gè)配置的作用,希望能通過(guò)下面的學(xué)習(xí)了解到Crank的工作基本原理

5.1. 啟動(dòng)Agent

crank-agent --dotnethome "/home/{your-account}/dotnet"
5.1.0.1. 啟動(dòng)Agent并指定dotnet環(huán)境
  • 格式:crank-agent –dotnethome "dotnet安裝地址"

  • crank-agent --dotnethome "C:\Program Files\dotnet" (windows)

  • crank-agent --dotnethome "/usr/share/dotnet" (Linux)

  • 在啟動(dòng)agent時(shí),強(qiáng)烈建議大家增加dotnethome 配置,為agent運(yùn)行指定環(huán)境,以免運(yùn)行任務(wù)時(shí)由于環(huán)境問(wèn)題而卡在install sdk這里

  • 因演示機(jī)器本地dotnet的使用的是安裝路徑為/home/gushoudao/dotnet,所以視頻中運(yùn)行的命令有所不同,這塊還需要根據(jù)本地的實(shí)際情況自行調(diào)整路徑即可 (因視頻錄制原因,在錄制結(jié)束后會(huì)停止agent,我們真實(shí)使用中啟動(dòng)后不需要退出,一旦退出agent,就無(wú)法執(zhí)行任務(wù))

5.1.0.2. 啟動(dòng)Agent并指定不清理臨時(shí)文件
  • crank-agen --no-cleanup (指定不清理臨時(shí)文件)

默認(rèn)agent執(zhí)行任務(wù)結(jié)束后會(huì)刪除當(dāng)前任務(wù)執(zhí)行過(guò)程中產(chǎn)生的臨時(shí)文件

5.1.0.3. 啟動(dòng)Agent并指定構(gòu)建任務(wù)的最大持續(xù)時(shí)間
  • crank-agent --build-timeout

默認(rèn)構(gòu)建任務(wù)的最大持續(xù)時(shí)間為10 minutes

更多配置點(diǎn)擊查看

5.2. 新建hello.benchmarks.yml配置

配置文件源碼來(lái)自hello.benchmarks.yml

imports:
  - https://raw.githubusercontent.com/doddgu/crank/sample/src/Microsoft.Crank.Jobs.Bombardier/bombardier.yml

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

scenarios:
  hello:
    application:
      job: server
    load:
      job: bombardier
      variables:
        serverPort: 5000
        path: /

profiles:
  local:
    variables:
      serverAddress: localhost
    jobs: 
      application:
        endpoints: 
          - http://localhost:5010
      load:
        endpoints: 
          - http://localhost:5010

5.3. 啟動(dòng)任務(wù)

啟動(dòng)agent(打開(kāi)放在一邊):

crank-agent --dotnethome "/usr/share/dotnet"

啟動(dòng)任務(wù)(另起一個(gè)新的Shell):

git clone https://github.com/doddgu/crank.git
cd crank
git checkout sample
crank --config ./samples/hello/hello.original.benchmarks.yml --scenario hello --load.framework net5.0 --application.framework net5.0

然后我們等待片刻會(huì)輸出以下結(jié)果

crank-agent:

crank:

| load                  |                |
| --------------------- | -------------- |
| CPU Usage (%)         | 39             |  CPU使用率
| Cores usage (%)       | 631            |  多核CPU使用率
| Working Set (MB)      | 35             |  內(nèi)存使用率
| Private Memory (MB)   | 35             |  進(jìn)程使用的私有內(nèi)存量
| Build Time (ms)       | 4,853          |  構(gòu)建應(yīng)用程序需要多長(zhǎng)時(shí)間(毫秒)
| Start Time (ms)       | 386            |  啟動(dòng)應(yīng)用程序需要多長(zhǎng)時(shí)間(毫秒)
| Published Size (KB)   | 66,731         |  已發(fā)布應(yīng)用程序的大小 (KB)
| .NET Core SDK Version | 5.0.403        |  .Net Core SDK 版本
| ASP.NET Core Version  | 5.0.12+0bc3c37 |  .Net Core版本
| .NET Runtime Version  | 5.0.12+7211aa0 |  .Net運(yùn)行時(shí)版本
| First Request (ms)    | 172            |  第一個(gè)請(qǐng)求耗時(shí)(這里請(qǐng)求是Get)
| Requests              | 2,086,594      |  總發(fā)送請(qǐng)求數(shù)
| Bad responses         | 0              |  糟糕請(qǐng)求數(shù)(響應(yīng)狀態(tài)碼不是2**也不是3**)
| Mean latency (us)     | 1,833          |  平均延遲時(shí)間
| Max latency (us)      | 89,001         |  最大延遲時(shí)間
| Requests/sec          | 138,067        |  每秒支持請(qǐng)求數(shù)
| Requests/sec (max)    | 255,442        |  每秒最大支持請(qǐng)求數(shù)

當(dāng)你能輸出以上信息的時(shí)候,證明了你已經(jīng)成功跑通了整個(gè)流程

在上面我們可以很清楚的看到場(chǎng)景hello下的測(cè)試結(jié)果,其中包含CPU使用率、多核CPU的使用率、內(nèi)存使用率以及每秒執(zhí)行的請(qǐng)求數(shù)等等指標(biāo)

在這一刻是不是突然覺(jué)得這個(gè)crank挺強(qiáng)大的,雖然還不清楚具體是咋做到的,但是真的很贊??!在這一刻是不是對(duì)它來(lái)了興趣,想知道它到底可以做什么,為什么可以輸出以上的結(jié)果?

6. 結(jié)尾

為確保后續(xù)不會(huì)因更新導(dǎo)致按照文檔操作不可用,源碼從官方源Fork了一份,其中絕大多數(shù)來(lái)自官方提供的Sample、部分文件為了更好的滿(mǎn)足個(gè)人習(xí)慣,會(huì)在一定程度上進(jìn)行調(diào)整。

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

參考鏈接:

開(kāi)源地址

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

如果你對(duì)我們的 MASA Framework 感興趣,無(wú)論是代碼貢獻(xiàn)、使用、提 Issue,歡迎聯(lián)系我們

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容