史上最細gRPC(Go)入門教程(十)---gRPC圧測ツールghz


由来:月を指すhttps://lixueduan.com
原文:https://lixueduan.com/post/grpc/10-benchmark/
本文は主にgRPCの圧力測定ツールghzを紹介し、ghzの設置、使用及び圧力測定計画の制定などを含む.
gRPCシリーズ関連コードはGithubを参照
1.インストール
直接Releaseページでバイナリファイルをダウンロードしたり、clone倉庫で手動でコンパイルしたりすることができます.
ダウンロードして解凍した後に使用することができます
#   
$ wget https://github.91chifun.workers.dev/https://github.com//bojand/ghz/releases/download/v0.94.0/ghz-linux-x86_64.tar.gz
ghz-linux-x86_64.ta 100%[===================>]  10.41M  1.84MB/s       5.7s  
#   
$ tar -zxvf ghz-linux-x86_64.tar.gz 
ghz
ghz-web
LICENSE
$ ls
ghz  ghz-linux-x86_64.tar.gz  ghz-web  LICENSE
#        
$ sudo vim /etc/profile
$ source /etc/profile
#             
$ cat /etc/profile
export PATH=$PATH:/home/lixd/17x/env

具体的な文法
ghz [] []

2.パラメータの説明
共通パラメータのみがリストされており、その他のパラメータは公式ドキュメントまたはヘルプコマンドを参照できますghz -h大きく分けて3つのパラメータがあります.
  • 基本パラメータ
  • 負荷パラメータ
  • 同時パラメータ
  • 2.1基本パラメータ
  • --config:プロファイルの場所指定
  • --proto:protoファイルの場所指定
  • protoファイルから関連情報を取得する
  • --call:呼び出し方法を指定します.
  • 具体フォーマットは . .
  • 如:--call helloworld.Greeter.SayHello
  • -c:同時要求数
  • -n:最大要求数、到達後試験終了
  • -d:要求パラメータ
  • JSON形式、例えば-d '{"name":"Bob"}'
  • -D:要求パラメータをファイル形式で指定し、JSONファイルの場所
  • 例えば-D ./file.json
  • -o:出力経路
  • stdoutにデフォルト出力
  • -O/--format:出力形式、複数種類の形式から選択可能
  • 見やすい:csv、json、pretty、html:
  • 入庫しやすい:influx-summary、influx-details:InfluxDB line-protocol形式の出力を満たす

  • 以上が関連する基本パラメータであり,これらのパラメータがあれば基本的にテストできる.
    2.2負荷パラメータ
    負荷パラメータは、主にghzが1秒あたり開始するリクエスト数(RPS)を制御する.
  • -r/--rps:指定RPS
  • ghz一定のRPSでテスト
  • --load-schedule:負荷スケジューリングアルゴリズム、値は以下の通り:
  • const:一定RPSであり、デフォルト呼び出しアルゴリズムでもある
  • step:ステップ成長RPS、配合が必要load-startload-stepload-endload-step-duration、およびload-max-duration等パラメータ
  • line:線形成長RPS、協力が必要load-startload-stepload-end、およびload-max-durationなどのパラメータ、実はlineはstepアルゴリズムでload-step-duration時間を1秒に固定しています.

  • --load-start:step、lineのスタートRPS
  • --load-step:step、lineのステップ値またはスロープ値
  • --load-end:step、lineの負荷終了値
  • --load-max-duration:最大持続時間、到着すれば終了
  • たとえば
    -n 10000 -c 10 --load-schedule=step --load-start=50 --load-step=10 --load-step-duration=5s
    

    50 RPSから10,000リクエストが完了するまで5秒ごとに10 RPSを追加します.
    -n 10000 -c 10 --load-schedule=step --load-start=50 --load-end=150 --load-step=10 --load-step-duration=5s
    

    50 RPSから10 RPSを5秒ごとに増加し、最大150 RPSに10,000リクエストが完了するまで増加します.
    -n 10000 -c 10 --load-schedule=line --load-start=200 --load-step=-2 --load-end=50
    

    200 RPSから、1秒ごとに2 RPSを50 RPSに下げ、10000リクエストが完了するまで下げます.
    lineは実はstepで、ただ–load-step-durationを1秒に固定しただけです
    2.3同時パラメータ
  • -c:併発woker数、
  • 注意:同時要求数ではない
  • --concurrency-schedule:同時スケジューリングアルゴリズム、および--load-schedule類似
  • const:コンカレント定数、デフォルト値
  • step:ステップアップ併発数
  • line:線形増加併発数
  • --concurrency-start:始発併発数
  • --concurrency-end:終了合併数
  • --concurrency-step:並行数ステップ値
  • --concurrency-step-duration:階段ごとに持続時間が必要
  • --concurrency-max-duration:最大持続時間
  • 例:
    -n 100000 --rps 200 --concurrency-schedule=step --concurrency-start=5 --concurrency-step=5 --concurrency-end=50 --concurrency-step-duration=5s
    

    固定RPS 200は、ワーカー数が5から5秒ごとに5ずつ増加し、最大50まで増加する.
    注:5つのworkerでも200 RPSを完了する必要があります.すなわち、各workerは40 RPSを完了する必要があります.50つのworkerでは、各workerで4 RPSを完了するだけで200 RPSに達することができます.
    負荷パラメータと同時パラメータを指定することで、より専門的に圧力測定を行うことができます.
    2.4プロファイル
    すべてのパラメータはプロファイルで指定できますが、これも比較的推奨されています.
    たとえば、
    {
         
        "proto": "/path/to/greeter.proto",
        "call": "helloworld.Greeter.SayHello",
        "total": 2000,
        "concurrency": 50,
        "data": {
         
            "name": "Joe"
        },
        "metadata": {
         
            "foo": "bar",
            "trace_id": "{
         {.RequestNumber}}",
            "timestamp": "{
         {.TimestampUnix}}"
        },
        "import-paths": [
            "/path/to/protos"
        ],
        "max-duration": "10s",
        "host": "0.0.0.0:50051"
    }
    

    3.使用
    このツールには2つの使い方があります.
  • 1)ghzバイナリファイル方式、コマンドラインパラメータまたはプロファイルでプロファイル情報を指定
  • 2)ghz/runnerプログラミング方式で使用し、コードで構成情報を指定
  • 両者は開き方が違うだけで、具体的な原理は同じです.
    トップページでは、以前のHelloWorldチュートリアルのGreeterサービスを開始します.
    lixd@17x:~/17x/projects/grpc-go-example/helloworld/server$ go run main.go 
    2021/04/17 10:53:46 Serving gRPC on 0.0.0.0:50051
    

    3.1命令ライン方式
    1)基本パラメータ
    まず基本パラメータを使用してテストを行います
    ghz -c 10 -n 1000 \
       --insecure \
       --proto ./hello_world.proto \
       --call helloworld.Greeter.SayHello \
       -d '{"name":"Joe"}' \
       0.0.0.0:50051
    
    --call helloworld.Greeter.SayHello:説明、具体的なprotoファイルは以下の通り
    //       ...
    package helloworld;
    service Greeter {
      rpc SayHello (HelloRequest) returns (HelloReply) {}
    }
    

    パッケージ名はhelloworld、サービス名はGreeter、メソッド名はSayHelloであることがわかります.
    結果は次のとおりです.
    Summary:
      Count:        1000
      Total:        87.65 ms
      Slowest:      6.97 ms
      Fastest:      0.12 ms
      Average:      0.75 ms
      Requests/sec: 11409.21
    
    Response time histogram:
      0.118 [1]     |
      0.803 [801]   |∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎∎
      1.487 [131]   |∎∎∎∎∎∎∎
      2.172 [27]    |∎
      2.857 [18]    |∎
      3.542 [12]    |∎
      4.226 [0]     |
      4.911 [0]     |
      5.596 [0]     |
      6.281 [0]     |
      6.966 [10]    |
    
    Latency distribution:
      10 % in 0.35 ms 
      25 % in 0.43 ms 
      50 % in 0.57 ms 
      75 % in 0.75 ms 
      90 % in 1.23 ms 
      95 % in 1.62 ms 
      99 % in 3.31 ms 
    
    Status code distribution:
      [OK]   1000 responses  
    

    ほとんどのリクエストは3 ms程度で応答できます.
    2)負荷パラメータ
    次に負荷パラメータを追加
    ghz -c 10 -n 1000 \
       --insecure \
       --proto ./hello_world.proto \
       --call helloworld.Greeter.SayHello \
       -d '{"name":"Joe"}' \
       --load-schedule=step --load-start=50 --load-step=10 --load-step-duration=5s \
       -o report.html -O html \
       0.0.0.0:50051
    

    今回はHTML方式で結果を出力することを指定し、実行が完了すると現在のディレクトリに出力されているHTMLファイルが表示されます
    $ ls
    report.html
    

    具体的な内容は以下の通りです.
    それに比べてHTML方式の方が直感的です.
    3)同時パラメータ
    最後にコンカレントパラメータを使用
    ghz -c 10 -n 10000 \
       --insecure \
       --proto ./hello_world.proto \
       --call helloworld.Greeter.SayHello \
       -d '{"name":"Joe"}' \
       --rps 200 --concurrency-schedule=step --concurrency-start=5 --concurrency-step=5 --concurrency-end=50 --concurrency-step-duration=5s \
       -o report.json -O pretty \
       0.0.0.0:50051
    

    今回CSV形式で印刷出力
    duration (ms),status,error
    1.05,OK,
    0.32,OK,
    0.30,OK,
    0.36,OK,
    0.34,OK,
    0.29,OK,
    0.40,OK,
    0.40,OK,
    0.62,OK,
    0.31,OK,
    0.30,OK,
    0.48,OK,
    

    CSVやJSON形式では、リクエストごとにその消費時間や状態などの情報が一覧表示されますが、HTMLに比べて直感的ではありません.
    3.2 ghz/runnerプログラミング方式
    プログラミング方式はより柔軟で、バイナリリクエストデータを直接使用できるのも便利です.
    完全なコードはGithubを参照
    関連コードは次のとおりです.
    package main
    
    import (
    	"log"
    	"os"
    
    	"github.com/bojand/ghz/printer"
    	"github.com/bojand/ghz/runner"
    	"github.com/golang/protobuf/proto"
    	pb "github.com/lixd/grpc-go-example/helloworld/helloworld"
    )
    
    //      https://ghz.sh/docs/intro.html
    func main() {
         
    	//   BinaryData
    	item := pb.HelloRequest{
         Name: "lixd"}
    	buf := proto.Buffer{
         }
    	err := buf.EncodeMessage(&item)
    	if err != nil {
         
    		log.Fatal(err)
    		return
    	}
    	report, err := runner.Run(
    		//      call host proto   data
    		"helloworld.Greeter.SayHello", //  'package.Service/method' or 'package.Service.Method'
    		"localhost:50051",
    		runner.WithProtoFile("../helloworld/helloworld/hello_world.proto", []string{
         }),
    		runner.WithBinaryData(buf.Bytes()),
    		runner.WithInsecure(true),
    		runner.WithTotalRequests(10000),
    		//     
    		runner.WithConcurrencySchedule(runner.ScheduleLine),
    		runner.WithConcurrencyStep(10),
    		runner.WithConcurrencyStart(5),
    		runner.WithConcurrencyEnd(100),
    	)
    	if err != nil {
         
    		log.Fatal(err)
    		return
    	}
    	//       
    	file, err := os.Create("report.html")
    	if err != nil {
         
    		log.Fatal(err)
    		return
    	}
    	rp := printer.ReportPrinter{
         
    		Out:    file,
    		Report: report,
    	}
    	//       
    	_ = rp.Print("html")
    }
    

    テストを実行すると現在のディレクトリに出力されるreport.htmlファイル
    $ go run ghz.go
    $ ls
    ghz.go  report.html
    

    4.まとめ
    ghz/runnerプログラミング+HTML形式で結果を出力することをお勧めします.
  • ghz/runnerプログラミング方式はバイナリ方式より柔軟
  • HTML形式出力結果より直感的