2. 堪比JMeter的.Net壓測工具 - Crank 進階篇 - 認識yml
1. 前言
入門篇我們已經成功執行hello.benchmarks.yml並輸出測試結果,本篇我們就hello.benchmarks.yml、以及執行的shell指令碼詳細解讀下其中的含義
2. 剖析hello.benchmarks.yml
2.1. job
- 在hello.benchmarks.yml中我們定義了一個新的job: server,並指定了倉庫資訊 ( 遠端倉庫 ):
repository:https://github.com/doddgu/crank.git # 倉庫源 branchOrCommit:sample # 分支 project: samples/hello/hello.csproj # 專案
- 並通過import匯入了bombardier.yml,其中定義了另外一個job: bombardier,並指定了倉庫資訊 ( 遠端倉庫 ):
repository: https://github.com/doddgu/crank.git branchOrCommit: sample project: src/Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj sourceKey: bombardier # 伺服器使用它來重用相同的原始檔夾。 noBuild: true # 定義 SourceKey時,指示是否仍應進行構建
2.2. scenarios
- 在hello.benchmarks.yml中我們定義了場景: hello,併為此場景指定了兩個任務:
- 第一個任務名為application,使用的是專案server
- 第二個任務名為load,並指定使用專案bombardier
2.3. variables 變數
-
在bombardier.yml中
- 定義了全域性變數: headers、presetHeaders(預設header)
- 定義了局部變數: connections、warmup、duration、requests、rate、transport、serverScheme等等
-
在hello.benchmarks.yml中為load定義了局部變數serverPort、path
2.4. profiles 配置
- 在hello.benchmarks.yml中我們
- 定義了配置local
- 並指定了區域性變數: serverAddress = localhost
- 為任務application、load指定了部署作業的endpoint 是 http://localhost:5010 (指定執行任務的Agent地址)
2.5. arguments 引數
- 在bombardier.yml中與variables同級的配置: arguments,此引數是在啟動job後傳遞的引數,其中定義的全域性引數、區域性引數資訊也都是為構建完整的引數做準備,bombardier真實的引數資訊是:
-c {{connections}} -w {{warmup}} -d {{duration}} -n {{requests}} --insecure -l {% if rate != 0 %} --rate {{ rate }} {% endif %} {% if transport %} --{{ transport}} {% endif %} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} {% if serverUri == blank or serverUri == empty %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} {% else %} {{serverUri}}:{{serverPort}}{{path}} {% endif %} {% if bodyFile != blank and bodyFile != empty %} -f {{bodyFile}} {% endif %} {% if verb != blank and verb != empty %} -m {{verb}} {% endif %}
3. 改造hello.benchmarks.yml
改造hello.benchmarks.yml,不考慮重用,最原始的程式碼如下
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"'
presetHeaders: none
jobs:
bombardier:
source:
repository: https://github.com/dotnet/crank.git
branchOrCommit: main
project: src/Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj
sourceKey: bombardier
noBuild: true
readyStateText: Bombardier Client
waitForExit: true
variables:
connections: 256
warmup: 15
duration: 15
requests: 0
rate: 0
transport: fasthttp # | http1 | http2
serverScheme: http
serverAddress: localhost
serverPort: 5000
path:
bodyFile: # path or url for a file to use as the body content
verb: # GET when nothing is specified
customHeaders: [ ] # list of headers with the format: '<name1>: <value1>', e.g. [ 'content-type: application/json' ]
arguments: "-c {{connections}} -w {{warmup}} -d {{duration}} -n {{requests}} --insecure -l {% if rate != 0 %} --rate {{ rate }} {% endif %} {% if transport %} --{{ transport}} {% endif %} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} {% if serverUri == blank or serverUri == empty %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} {% else %} {{serverUri}}:{{serverPort}}{{path}} {% endif %} {% if bodyFile != blank and bodyFile != empty %} -f {{bodyFile}} {% endif %} {% if verb != blank and verb != empty %} -m {{verb}} {% endif %}"
onConfigure:
# - job.timeout = Number(job.variables.duration) + Number(job.variables.warmup) + 10;
endpoints:
- http://localhost:5010
server:
source:
repository: https://github.com/doddgu/crank
branchOrCommit: sample
project: samples/hello/hello.csproj
readyStateText: Application started.
endpoints:
- http://localhost:5010
scenarios:
hello:
application:
job: server
load:
job: bombardier
variables:
serverPort: 5000
path: /
4. 解讀crank shell
之前我們通過shell執行:
-
crank --config hello.benchmarks.yml --scenario hello --profile local --load.framework net5.0 --application.framework net5.0
- 其中crank 是固定的、代表:Crank Controller
- --config:固定的配置,指執行哪個yml配置,每次僅能指定一個yml配置
- --scenario:固定的配置,設定場景是hello
- --profile:固定的配置,非必選,可多次設定,指定當前Crank命令申請的配置是local,使用local下配置的所有資訊
- --load.framework: 格式:<任務名>.framework,為任務load指定framework的執行框架版本是net5.0、--application.framework同理
-
改造hello.benchmarks.yml,因為移除了profile,所以執行: crank --config hello.yml --scenario hello --load.framework net5.0 --application.framework net5.0 即可
5. 疑問
- 為什麼啟動crank時要增加--application.framework net5.0?
- 安裝crank要求必須有net5.0的環境,所以指定net5.0不需要再單獨安裝框架環境
- 為什麼啟動crank時不指定framework時預設是netcore3.1呢?
- 使用記事本開啟hello.csproj、Microsoft.Crank.Jobs.Bombardier.csproj 即可瞭解
- scenarios節點下application以及load兩個節點名稱可以更換嗎?只能有兩個節點?
- 節點名稱不固定,可以更換,也沒有限制必須是兩個節點,具體多少個節點根據自己的需要來
6. 結尾
通過上面的學習,我們也已經完全的瞭解了各配置的作用,但對bombardier.yml與開源專案bombardier存在什麼樣的聯絡還不清楚,以及為什麼叫做bombardier.yml而不是其他名字,並且是如何實現效能指標的輸出,接下來就會講到bombardier.yml與開源專案bombardier的關係,以及wrk.yml與wrk的關係
原始碼地址:https://github.com/doddgu/crank/tree/sample
開源地址
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,歡迎聯絡我們