【クラウドネイティブ会議】負荷検証を「やった」で終わらせない、実際のアクセスログとAIでシナリオを継続的に育てる仕組み
タクシー配車サービスシステムに必要な継続的な負荷検証の仕組みを解説したセッションを紹介する。
9:10
タクシー配車サービスを安定して運用するには、需要のピークを想定した負荷検証が欠かせない。しかし十分なトラフィックを流していても、実際の利用パターンをシナリオが網羅していなければ、障害を防げないことがある。「クラウドネイティブ会議」のセッション「継続的な負荷検証を目指して」では、GO株式会社の山下和彦氏が、サービス障害から得た教訓をもとに、Grafana Loki、Claude Code、k1LoW/runnを組み合わせ、本番環境のアクセスログから負荷検証シナリオを継続的に作成・検証する仕組みを紹介した。本稿では、人の作業サイクルをAIに移しながら、最終判断を人が担う取り組みをレポートする。
負荷の大きさではなくシナリオの網羅性が問題だった
GO株式会社の山下和彦氏は「継続的な負荷検証を目指して」と題し、タクシー配車サービスで発生した障害と、その経験を踏まえて構築した負荷検証の仕組みを紹介した。山下氏は同社のバックエンド開発部に所属し、以前はホスティング事業やプラットフォームエンジニアリングに携わっていた。
発端となったのは、タクシー需要のピーク時に発生したサービス障害である。退勤時間帯の大雨や飲み会の時間帯、年末の忘年会シーズン、終電後などは、タクシーへの需要が集中しやすい。障害発生時にはDBコネクションがスタックして接続できなくなり、それが連鎖してメインAPIが応答不能になった。DBへの対応後、トラフィック・シェーピングによって復旧したという。
原因は大きく2つあった。1つは、本来レプリカDBに流すべきSELECTクエリがプライマリDBに多数送られていたこと。そしてもう1つは、トランザクション内で外部APIを呼び出していたことである。そのため、外部APIの応答を待つ間もトランザクションが維持され、実行時間が長期化していた。その結果、Wait系のメトリクスが上昇し、DBの処理能力が限界に達したというわけだ。
障害に備え、クエリチューニングとDBリファクタリング、パフォーマンスの悪いコードの書き換え、負荷検証も進めていた。負荷検証にはGoでスクラッチ開発したソフトウェアを使用し、ユーザーがアプリでタクシーを探し、乗車して支払いを行う基本的な配車シナリオを高速に繰り返していた。並列度や実行地域も制御でき、本番以上の負荷をかけることも可能だった。
「障害が起きた時以上の負荷を流して確認していたので、かなり安心して臨んでいました」と山下氏は振り返る。それでも障害が発生したのは、シナリオの網羅性が不足していたためである。
『GO』アプリには、周辺のタクシーが少ない場合など、特定の条件でのみ呼び出されるエンドポイントがある。ところが負荷検証には、そのピーク時特有のエンドポイントが含まれておらず、しかもそのようなエンドポイントこそ処理負荷が高かったのだ。
負荷検証を「やっている」ことと、必要な利用パターンを「カバーしている」ことの間には大きな差がある。山下氏はこの障害から、本番で発生するシナリオを継続的に取り込む必要性を認識した。
増え続けるシナリオをAIで補う
障害後、同社では可観測性の向上、レプリカDBを利用するためのアプリケーション改修、トランザクション実行時間の削減、縮退モードの開発を進めた。外部API呼び出しをトランザクションの外に切り出すほか、負荷が高まった場合にトラフィックや配車を制御できる仕組みも整えた。
そのうえで着手したのが、継続的な負荷検証である。継続が難しい理由の1つは、サービスが常に変化することにある。新しいエンドポイントは日々追加され、リリース後に特定のユーザーやデータだけで負荷が高まることもある。一方、開発現場では新機能が優先され、負荷検証用のシナリオ作成は後回しになりやすい。
「普段は新規開発をどんどん進めているので、負荷検証のシナリオを作り続けるのは簡単ではありません」と山下氏は語った。
そこで山下氏が着目したのがAIである。ただし、AIにシナリオを作らせるだけでは十分ではない。生成物の妥当性をレビューし、実際に動作するかを確認する必要がある。また、精度の高いシナリオを一度の指示で作らせることも難しい。
こうした課題に対し、同社ではシナリオワークフローエンジンの「k1LoW/runn」を採用した。runnはYAMLでテストシナリオを宣言的に定義でき、人が読んでも処理の流れを理解しやすく、AIにコンテキストとして渡しやすい。
もともとはE2Eテストなどに利用できるツールだが、Goからライブラリとして実行できるため、負荷検証にも流用できる。Goのテンプレート埋め込みに対応し、includeを使って認証処理などを共有資産化できるほか、デバッグ出力によって失敗原因も追いやすい。「YAMLで宣言的に書けるので、人間にも見やすく、AIとも協業しやすいところが大きな利点です」と山下氏は説明した。
人の検証サイクルをAIに移植する
AIが生成したシナリオを実用化するには、作成後に実行し、失敗したらログを確認して修正する必要がある。山下氏は、人がシナリオを作る際の一連の行動をAIに与える仕組みを構築した。
構成要素は、Claude Code、runn、Grafana Loki、そして本番環境とdev環境のAPIサーバーである。まずClaude Codeが本番環境のLokiに保存されたアクセスログを分析し、実際のAPI呼び出し順序からYAML形式のシナリオを作成する。次にrunnを使ってdev環境で実行する。結果はdev環境のLokiに出力され、Claude Codeがログを読み、想定したルートを通っているかを確認する。失敗した場合は原因を分析し、シナリオを修正する。
この処理を実現するため、2つのAgent Skillsを用意した。1つ目の「extract-scenarios」はログを読み、シナリオを作成するスキルである。AIにはMCP経由でGrafana Lokiへのアクセス手段を与え、本番環境のアクセスログから、ユーザー向けアプリとドライバー向け端末がどのAPIをどの順番で呼び出しているかを分析させる。
発見したパターンからrunbook YAMLを生成するが、似たシナリオが増えないよう、既存シナリオとの重複を確認し、新規性のある候補だけを人間に提案する。
そして2つ目の「run-stress」は、作成したシナリオをdev環境で実行して検証するスキルである。内部ではrunnをGoライブラリとして組み込んだCLIを利用する。失敗するとdev環境のLokiからログを取得し、原因を調査して修正する。偶然1回成功しただけでは不十分として、「3回連続でパスするまで直し続けてください」という条件も与えている。
「人がシナリオを作る時に行うサイクルそのものを、AIに移植したような仕組みです」と山下氏は表現した。
この方法により、ピークタイムや特定の時間帯にしか発生しない利用パターンを、膨大なログから抽出できるようになった。人が見落としていた重いAPIが見つかる場合もあったという。
またYAMLで記述されたrunnのシナリオは、ドキュメントとしても役立った。新しく参加した開発者がAPIの呼び出し順序を理解したり、dev環境で実際の配車フローを試したりする用途にも利用できる。
自動化しすぎず人の判断を残す
実用的な負荷検証を行うため、検証環境にも複数の工夫が施されている。DBには本番環境に相当する大量のレコードを用意し、データ量が少ない環境では表面化しにくい性能問題を再現できるようにした。外部通信はすべてMock化し、メール送信などが実際に発生しないようにしている。
テストに使うユーザーやドライバーは、関連レコード数が多いものを自動的に選択する。紐づくデータが少なければ、N+1クエリが存在していても処理がすぐに終わり、十分な負荷にならないためである。
さらにrunnのHTTPクライアントを共有して接続コストを抑え、負荷をかける側が先に限界に達しないよう、負荷クライアントをワーカー化した。親プロセスが複数の子プロセスにタスクを振り分け、並列にシナリオを実行する。また、Grafana MCPの利用では、社内のアカウント管理と連携した認証・認可を実装し、閲覧できるNamespaceを制御している。
一方、現時点ですべてをAIに任せているわけではない。シナリオ生成の仕組みを起動することや、負荷検証そのものの実施は人が行う。本番とほぼ同等の構成を動かすにはコストがかかるため、常時自動実行する合理性がまだ低いからである。
AIが作ったシナリオの妥当性も人が確認する。技術的に正しく動いても、そのエンドポイントを重点的に検証することにビジネス上の意味があるとは限らない。負荷検証の結果も、最終的には担当者がGrafanaのダッシュボードを確認して評価している。「AIが作ったものが、本当にビジネス的に意味のあるシナリオなのかは、人が見ています」と山下氏は語った。
今回の取り組みでは、ログ分析、シナリオ候補の作成、dev環境での反復的な動作確認をAIが担い、実行時期やシナリオの価値、検証結果の評価を人が判断する。このようにAIと人が分業しているわけだ。
山下氏は最後に、負荷検証シナリオを継続的に開発するには、AIに「人が扱うのと同じ情報と操作手段を与えることが重要」だとまとめた。そのうえで、runnのように人間とAIの双方が理解できる既存の仕組みを組み合わせることが、継続的な負荷検証を現実的な運用へ近づけるとした。
- この記事のキーワード
この記事をシェアしてください
