😇

負荷試験を恐れないための基本あれこれ

2022/01/14に公開

私は負荷試験が怖いです。
それなりに慣れたつもりですが必要となる知識領域は広く、
トライ&エラーの繰り返しでなかなかに大変な作業となります。
そんな自分や、ビギナーが恐れず挑めるように基本部分をまとめてみます。

負荷試験の目的

負荷試験とは、機器やソフトウェア、システムのテストの一種です。
行う目的としては下記があげられます。

性能の計測

負荷を高めたときの状態や性能などを計測し、どのくらいの負荷まで正しく動作するかを検証します。

高負荷時の性能改善

処理が詰まりパフォーマンスが出ない場合のボトルネックとなる部分を特定します。
特定後、ボトルネック解消を行いパフォーマンス向上につなげます。

ハードウェアスペックの選定

試験結果から実際にサービスで運用する本番構成のスペックを確定させます。

スケーラビリティ(拡張性)の確認

スケールアウト等を行った際に、期待どおりに性能が拡張されるかを検証します。

関連用語

負荷試験を実施するにあたり良く目にする単語をいくつか説明します。

スループットとレイテンシ

  • スループット
    • 単位時間に処理を行う量のこと
    • 1秒間にさばけるリクエスト数をrps(Request Per Second)という表記がよく使われます。
  • レイテンシ
    • 処理時間のこと
    • Webシステムで言うとリクエストからレスポンスまでどれだけかかったか。

試験実施時には、目標設定として

スループット:〇〇rps

レイテンシ:n秒以下

といった目標設定を行います。

可用性(アベイラビリティ)

システムがサービスを正常に提供できる状態のこと。
可用性99.99%というのが、99.99%の時間正常利用できるということになります。

99.99%というのはとても高い数字ではありますが、1年ですと53分間はサービスダウンしている、ということでもあります。

単一障害点と冗長化

  • 単一障害点
    • そこが故障するとサービスを提供できなくなってしまう箇所
  • 冗長化
    • 単一障害点をなくすこと

例えばwebサーバ一台で運用しているサービスを考えてみましょう。
上記構成ではwebサーバがダウンした場合、停止中はユーザーへのサービス提供ができなくなります。
webサーバが単一障害点になっている状態です。

これを解消するのが冗長化です。
ロードバランサを介し、バックエンドのwebサーバを複数台構成にします。
これにより1台ダウンした場合でも、もう1台が稼働していればLBにより振り分けられ
サービスを停止を防ぐことができます。

スケーラビリティ

負荷の増大に応じて、どれだけ柔軟に性能や機能を向上、拡張できるかを表すものです。
スケールには下記のような方法があります。

  • スケールアウト
    • マシンの台数を増やして、性能向上をはかります
  • スケールイン
    • マシンの台数を減らして、コストダウンをはかります。
  • スケールアップ
    • マシン自体のスペックをあげて、性能向上をはかります。
  • スケールダウン
    • マシンのスペックを下げて、コストダウンをはかります。

リソースに余裕があればスケールイン or スケールダウンにてコストダウンを、
負荷が厳しい場合には、スケールアウト or スケールアップにて性能向上を

といったようにサービスの負荷状況をみて、最適な構成に変更していきます。

作業手順

1. スケジュールを決める

サービス開始予定が決まっていれば、そこから逆算しましょう。

  • サーバー構築
  • 負荷試験用のシナリオ作成
  • 試験実施
  • チューニング
  • 試験結果レポート作成

といった作業が想定されます。

不確定要素が多いため、なるべく余裕を持ったスケジュールを組んでおきましょう。
そもそも予算が確保されていないなどは泣きを見ることになるので、
早い段階で期間と人員を押さえておく必要があります。
エンジニアサイドからしっかりと伝えておきましょう。

2-1. 目標の設定:レイテンシ

私が携わってきた案件はいずれも受託案件でした。
目標値に関してはクライアント企業によっては、先方から具体的に提示いただくこともあります。
大手企業は特に具体的に設定されてるところが多い印象です。
逆に歴史が浅い企業様では体制が整っていない関係から、こちらに設定を任されることもあります。

さて具体的にどれくらいに設定するかは悩みどころです。

私が携わったソシャゲ案件では、
"APIリクエストの95%が1秒以内"
という目標でやっていました。

サービスにもよりますが、ユーザーが"遅い"と感じない落としどころを設定します。

2-2. 目標の設定:スループット

スループット:〇〇rps

を設定する必要がありますが、この算出は初めてだと検討つかない方も多いかと思います。

まずは一定時間にどの程度アクセスがあるかを考えてみましょう。

1日の利用人数(人 / 日) × 1人あたりの1日の平均アクセス数(回 / 人) = 1日の総アクセス数(回 / 日)
1日の総アクセス数(回 / 日) ÷ 1日の秒数86,400(秒 / 日) = 1日の平均rps(回 / 秒)
1日の平均rps(回 / 秒) × 1日の平均アクセス数に対する最大ピーク時の倍率 = 最大rps(回 / 秒)

1日の利用者数

サービスのDAU想定があるはずなので、それを確認しましょう。
未定なら決めてもらいましょう。これがなければ始まりません。

1日あたりの平均アクセス数

こちらはサービスによりけりです。
開発がある程度進んでいる場合であれば、デバッグ用のアプリなどで実際に1時間ほどプレイを行いアクセスログから算出できるでしょう。

平均アクセスに対する最大ピーク時の倍率

私が携わった案件はソシャゲ案件でしたので、過去案件のHAU数等を参考に設定しました。
ソシャゲでは、通勤時間帯、昼休み、18時以降~0時、といった時間帯にアクセスが増える傾向がありました。

サービスによってこの辺はかなり変わってくるかと思います。
人づてに聞いた話では、マ〇ドのアプリとかは昼食時にガッとアクセスが跳ね上がるとか。

表で算出してみる

仮で

DAU:10万
平均アクセス:800
ピーク時倍率:3

で計算してみましょう。

項目名 数値
DAU 100000
1人1日の平均アクセス 800
1日の総アクセス 80000000
1日の平均rps 925.9259259
最大ピーク時の倍率 3
最大rps 2777.777778

最大rpsが 2777 となりました。
キリが悪いので、切り上げして 2800 rps を目標とする。

といった形で目標値を決めました。

3. 環境構築

負荷試験の環境は本番環境と同構成にします。

本番サーバーとは別に別途負荷がけ用の攻撃サーバーが必要になります。
私が携わった案件ではApache jmeterというツールを使用していました。

jmeter用のサーバーは、

jmeter client 1台

jmeter server 複数台

といった構成になります。
jmeter clientが各jmeter serverにシナリオに沿って負荷がけを行うよう指示を出す形になります。
実案件ではjmeter serverは5台で試験を行いました。

4. 負荷試験のシナリオ作成

jmeter等の攻撃ツールでは、API実行順や、同時実行数など制御するシナリオを作成できます。

ユーザーの行動を想定してシナリオを組み、実際のサービスにかかる負荷を再現させます。

※シナリオの作成の仕方については、ツールの詳細のお話になるのでここでは控えます。

5. 実施前の暖気申請

※この作業はAWSでも最近は不要らしいです

環境構築完了、シナリオも作成済でいざ実施の前にAWSではLBの暖気申請が必要でした。
LBは負荷に応じて自動でスケールするのですが、いきなり大量のリクエストを投げすぎると
スケールが間に合わずリクエストをさばききれなくなります。

そのため試験実施日程を伝え、あらかじめスケールした状態にしておく必要がありました。

GCPにおいてはLBの暖気申請は必要なかったです。

6. 試験の実施

実施中はひたすらモニタリングです。

サブシステム WATCHすべきもの、方法を把握しておくべきもの
ネットワーク 転送量
ハードウェアやOS CPU, メモリ, プロセス数, SWAP, Load Average
TCP 外部へのコネクション状況(ESTABLISH や FIN WAIT など)
ディスク IOPS, R/W 転送データ量
サーバミドルウェア(Apache, MySQL) コネクション数
アプリケーション プロファイラーにて監視
MySQL Slow Query, Process List

AWSではCloudWatchというツールでモニタリング可能です。
またモニタリングツールの他、サーバーにログインして試験中のリソースも監視することになります。

  • top, htop:CPU, メモリ使用量等
  • netstat, ss:TCPコネクション数
  • vmstat, dstat:1秒毎に実行して、リソース状況の記録

その他、PHPではxdebugによるプロファイルも行っていました。
実行処理をトレースして、結果をダンプし専用のツールでどこの処理に時間がかかっているか可視化されます。

7. 結果の確認

jmeterの実行が終わったら、結果を回収します。
試験結果から、ボトルネックを特定する戦いになります。

APIのロジックが悪いのか
SQLのクエリが悪いのか
Webサーバのパラメータ設定がまずいのか
コネクションを食いつぶしていないか

etc

8. チューニング

ボトルネックが特定できたらチューニングを行っていきます。

SQLのクエリを修正する

適切にINDEXを張る

Webサーバのパラメータ調整

アプリケーションのロジック修正

etc

9. 試験とチューニングの繰り返し

あとはひたすら6 ~ 8の繰り返しです。

チューニングは一度に複数の調整をやりすぎると、どれが影響をもたらしたのか特定しづらくなるため
なるべく少しづつ調整しましょう。

ボトルネックが解消され、良い感じに負荷がかかるようになってくれば
シナリオのリクエスト数調整、webの増大なども行い、限界を探っていきましょう。

10. レポート作成

目標達成し試験が完了したらレポートを作成しましょう。
企業ごとに決まったフォーマットがあるかもしれません。事前に確認しておきましょう。

終わりに

以上、負荷試験のおおまかな流れでした。

過去具体的に躓いたところなどはまた別記事をあげようと思います。

参考文献


Amazon Web Services負荷試験入門

AWSと書いてますが、他クラウドでも全然通用する内容です。

序章の"間違いだらけの負荷試験"は耳が痛い内容でいっぱいです。

Discussion