Skip to content

Instantly share code, notes, and snippets.

@neguse
Last active July 11, 2018 15:14
Show Gist options
  • Save neguse/03f109479c0e4de3beae to your computer and use it in GitHub Desktop.
Save neguse/03f109479c0e4de3beae to your computer and use it in GitHub Desktop.

サーバの負荷試験について、やったことの紹介

言いたいこと

  • サーバの負荷試験をやってみた
  • やってよかった
  • もうちょっといい方法があったら教えてほしい

家庭用ゲームのゲームサーバとは

  • 以下のような機能をもつ(タイトルごとに異なる)
    • ユーザ間のマッチング
    • ユーザ単位の情報の更新・取得
    • グローバルな情報の更新・取得

サーバの負荷試験とは

  • サーバに負荷をかけて、キャパシティを確認する
  • ロードテスト、ストレステストとも

負荷試験のやりかた(1/3)

  • テストシナリオの設計
    • どういうシチュエーションを確認したいか決める
  • テストシナリオの実装
    • そのシチュエーションを再現できる仕組みの用意
  • テストシナリオの実行、モニタリング
    • そのシチュエーションを再現し、キャパシティを確認する

負荷試験のやりかた(2/3)

  • テストシナリオ実行プログラム(負荷試験BOT)
    • 実装されたシナリオ通りの通信を実行
    • 1プログラムで複数(大量)のユーザアクセスを模倣する
    • レスポンスタイムやエラー数を測定して出力

負荷試験のやりかた(3/3)

  • 負荷試験BOTの作り方
    • Webアプリケーションの負荷試験ツールはいろいろあるが…
      • Apache Bench、Gatling、JMeter、Locust などなど
    • フレームワークからスクラッチで実装してます
      • シナリオが複雑なので、プログラムで記述したい
      • 通信のしかたが特殊なことがあるので、できるだけ低レイヤーから構築したい
      • サーバエンジニアが実装するので、慣れた言語で書きたい

BOTシナリオの例(1/2)

説明のための架空のゲームと、そのシナリオ

  • 対戦ゲーム A(仮)
    • ゲーム起動後に自動的にサーバへログインします
    • ログイン中は、自動的にサーバに対して1分ごとに通知確認を行います
    • ログイン中は、特定のメニュー操作で対戦モードに移行します
      • 対戦モードでは、まずサーバに対してマッチング要求を行います
      • マッチング要求中は、10秒に1回、マッチングが完了したかの確認を行います
      • マッチングが完了したら、試合が開始されます
      • 試合が終わったらサーバに試合結果を送信します

BOTシナリオの例(2/2)

なんとなくGo言語っぽい言語で書いた擬似コード (実際のとは違います)

こういう1ユーザごとのアクセスシナリオを用意して、同時に大量に実行する

ふりかえり(1/2)

  • 実装言語について

    • Golangみたいな、大量の軽量スレッドが扱える言語処理系だと実装が楽
    • そうでない言語で実装すると、非同期処理が大量でつらい
  • 負荷試験の意義について

    • キャパシティや、高負荷状態特有のバグが事前にわかる
    • 事前にわかっていれば対策をうてる
    • 試験で確認できた範囲内は、サービス開始後での負荷の問題は起こらなかった
    • やってよかった

ふりかえり(2/2)

  • テストシナリオの妥当性をどう担保するかが課題
    • 想定が外れてしまうと過負荷になりうる
    • ある程度参考にできる情報はあるが…
      • ベータテストとかでユーザ動向を調べておくとか
    • なにかいい方法があれば教えてください

Q&A

  • Q, サーバ上のデータセットが大きくないと負荷できなくない?
    • A, そうなので、プロダクション規模のデータセットを作って実行します
    • 負荷試験BOTを事前に長期間動かしたり、専用のダミーデータ作るBOT作ったり
  • Q, BOT起動のタイミングによっては負荷が偏ったりしない?
    • A, ramp up期間を実装してあって、徐々に起動するようになってます
    • かたよる状況(ログインラッシュとか)もそれはそれで見たいときがある
  • Q, 通信ログをリプレイするような方法で負荷試験できない?
    • A, 以前の通信データをもとにリクエストを送信するようなケースに対応できないと考えています
    • たとえば、例であったマッチングのreqIdのように、リクエストのパラメータが状況に応じて変わる部分をどうするかという問題がある

参考になりそうなリンク

package main
import (
"time"
)
func botScenario() {
ログインする()
// ログイン中は1分ごとに通知確認
go func() {
for {
通知確認()
sleep(1 * time.Minute)
}
}()
// 10分ごとにマッチング実行→3分間試合
go func() {
for {
reqId := マッチング要求登録(マッチング条件)
var result
for {
result = マッチング完了確認(reqId)
if result.Complete {
break
}
sleep(10 * time.Second)
}
sleep(3 * time.Minute) // 試合してるつもり
試合結果送信()
sleep(10 * time.Minute) // 試合と試合の間隔、平均的にはこのぐらい
}
}()
wait()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment