- サーバの負荷試験をやってみた
- やってよかった
- もうちょっといい方法があったら教えてほしい
- 以下のような機能をもつ(タイトルごとに異なる)
- ユーザ間のマッチング
- ユーザ単位の情報の更新・取得
- グローバルな情報の更新・取得
- サーバに負荷をかけて、キャパシティを確認する
- ロードテスト、ストレステストとも
- テストシナリオの設計
- どういうシチュエーションを確認したいか決める
- テストシナリオの実装
- そのシチュエーションを再現できる仕組みの用意
- テストシナリオの実行、モニタリング
- そのシチュエーションを再現し、キャパシティを確認する
- テストシナリオ実行プログラム(負荷試験BOT)
- 実装されたシナリオ通りの通信を実行
- 1プログラムで複数(大量)のユーザアクセスを模倣する
- レスポンスタイムやエラー数を測定して出力
- 負荷試験BOTの作り方
- Webアプリケーションの負荷試験ツールはいろいろあるが…
- Apache Bench、Gatling、JMeter、Locust などなど
- フレームワークからスクラッチで実装してます
- シナリオが複雑なので、プログラムで記述したい
- 通信のしかたが特殊なことがあるので、できるだけ低レイヤーから構築したい
- サーバエンジニアが実装するので、慣れた言語で書きたい
- Webアプリケーションの負荷試験ツールはいろいろあるが…
説明のための架空のゲームと、そのシナリオ
- 対戦ゲーム A(仮)
- ゲーム起動後に自動的にサーバへログインします
- ログイン中は、自動的にサーバに対して1分ごとに通知確認を行います
- ログイン中は、特定のメニュー操作で対戦モードに移行します
- 対戦モードでは、まずサーバに対してマッチング要求を行います
- マッチング要求中は、10秒に1回、マッチングが完了したかの確認を行います
- マッチングが完了したら、試合が開始されます
- 試合が終わったらサーバに試合結果を送信します
なんとなくGo言語っぽい言語で書いた擬似コード (実際のとは違います)
こういう1ユーザごとのアクセスシナリオを用意して、同時に大量に実行する
-
実装言語について
- Golangみたいな、大量の軽量スレッドが扱える言語処理系だと実装が楽
- そうでない言語で実装すると、非同期処理が大量でつらい
-
負荷試験の意義について
- キャパシティや、高負荷状態特有のバグが事前にわかる
- 事前にわかっていれば対策をうてる
- 試験で確認できた範囲内は、サービス開始後での負荷の問題は起こらなかった
- やってよかった
- テストシナリオの妥当性をどう担保するかが課題
- 想定が外れてしまうと過負荷になりうる
- ある程度参考にできる情報はあるが…
- ベータテストとかでユーザ動向を調べておくとか
- なにかいい方法があれば教えてください
- Q, サーバ上のデータセットが大きくないと負荷できなくない?
- A, そうなので、プロダクション規模のデータセットを作って実行します
- 負荷試験BOTを事前に長期間動かしたり、専用のダミーデータ作るBOT作ったり
- Q, BOT起動のタイミングによっては負荷が偏ったりしない?
- A, ramp up期間を実装してあって、徐々に起動するようになってます
- かたよる状況(ログインラッシュとか)もそれはそれで見たいときがある
- Q, 通信ログをリプレイするような方法で負荷試験できない?
- A, 以前の通信データをもとにリクエストを送信するようなケースに対応できないと考えています
- たとえば、例であったマッチングのreqIdのように、リクエストのパラメータが状況に応じて変わる部分をどうするかという問題がある