Upgrade to Pro — share decks privately, control downloads, hide ads and more …

k6による負荷試験 入門から日常的な実践まで/Re:TechTalk #01

k6による負荷試験 入門から日常的な実践まで/Re:TechTalk #01

FUJIWARA Shunichiro

March 26, 2025
Tweet

More Decks by FUJIWARA Shunichiro

Other Decks in Technology

Transcript

  1. シナリオの作り方 まず単一URL連打から import http from 'k6/http' import { check }

    from 'k6' export default function () { let res = http.get('https://example.com/') check(res, { 'success': (r) => r.status === 200 }) } いきなり複雑なものは書かない
  2. k6で実行 最初は「並列度(vus=virtual users)」= 1 から $ k6 run --vus 1

    --duration 300s simple.js checks.............: 99.98% ✓ 52644 ✗ 6 http_req_duration..: avg=285.56ms min=32.93ms med=144.61ms max=30.05s p(90)=521.34ms p(95)=788.36ms http_reqs.. ......: 52650 172.404676/s (いっぱい出力があるけど)とりあえずこの3個を見る checks: コード内の check() の成功・失敗数 レイテンシ: http_req_duration スループット: http_reqs
  3. 結果を評価する 1. k6の出力とサーバー側のメトリクスに齟齬がないか →メトリクスの取得がおかしい可能性が高いので見直す 2. checksは想定通りか →エラーが目標/想定より多い場合は性能を評価する意味がない 原因を調査する 3. レイテンシは目標に達しているか

    →これ以上並列度を増やすのはたいてい無意味 ボトルネックの調査をする 4. スループットは目標に達しているか or →並列度を2倍にして変化を見る 無闇に変数を変えて試さない
  4. シナリオを増やしていく 1. 参照系のリクエスト/画面遷移を足す 2. ログイン/更新系のリクエストを足す (コードの具体例はISUCON本 4章に) 本番のアクセスパターンと負荷を網羅しようと思うのはやめよう(大変) 1. 一連のシナリオごとに実行する

    例: トップ→ログイン→マイページ→お知らせを見る これだけでも特定の箇所で大きな問題がある場合には改善点が分かる 2. 複数のシナリオを混ぜて実行する 複数シナリオを実際に想定される程度の割合で混ぜる
  5. クライアント側で起きる問題の頻出例 (ISUCON本 9章を参照) ネットワーク帯域が上限を打っている 1Gbpsの回線で1MBのレスポンスを取得→(たったの)125req/sec(=125MB/sec) HTTP Keep-Aliveが無効になっている TCP 3 way

    handshake / TLS handshake のオーバーヘッドが大きい 無駄にファイルディスクリプタ(ソケット)を使う Goで自作した場合にやりがち: http.Response.Body を全て読み切らない →次のリクエスト時は新規のTCP接続になる ファイルディスクリプタを使い果たしている ulimit -n (max open files)がデフォルトの1024 ローカルポート(エフェメラルポート)が枯渇している 大量/高速にリクエストを送受信すると使い果たす
  6. 用意したシナリオ 1. トップページにアクセス 2. トップページから呼ばれるAPI(認証なし)を複数並列で叩く 3. ログインフォームにアクセス 4. ユーザー名とパスワードをPOSTしてログインする 5.

    ログインセッションが必要なAPI(要認証)を叩く コンポーネント(CDN, LB, WebApp, MySQL, Redis)を一通り通過する ストレージからの読み込み、書き込み処理が両方ある これを回しながら作業すると、各コンポーネントのエラーの発生と回復が検知できる
  7. GitHub Actions等でも日常的に実行 k6 は CLI ツールなので GitHub Actions などでも簡単に実行できる リポジトリにシナリオを置いておく

    本番/ステージング/開発環境等に向けられるようにしておくと便利 on: workflow_dispatch: inputs: target: description: "target to load test" required: true type: string jobs: load_test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: grafana/setup-k6-action@v1 - uses: grafana/run-k6-action@v1 with: path: | ./load_tests/${{ inputs.target }}.js