図を書いて気分転換したくなったので、アーキテクチャについて軽く触れます。
細かくは省いて、負荷試験の大雑把なサーバー構成にはどのような選択肢があるのか、の事例を出していきます。
登場人物
超ざっくり分けると3つに分類されます。User | 負荷試験の実行命令を出すための作業環境 |
Client | 負荷試験ツールを実行するためのサーバー |
Server | アプリケーションを稼働するためのサーバー |
基本AWS内での利用を想定していますが、User と Server は別にどこの環境でも大丈夫なようにしています。Client は ECS Fargate で使い捨て。
私の場合、実際にどのような構成で試験できるようにしたのか、を紹介していきますが、これだけ見ると至って普通な内容かもしれません。
1:1 ダイレクト型
まずは最もシンプルな構成で、主に動作テスト用です。これだと普通にLocustを動かすのと変わらない構成です。実行命令と負荷リクエストを出すサーバーが同じで、任意の1ホストへリクエストを送信します。
Server は Host を指定するだけなので、経路が通っていれば Private 経由でイケますし、開放されていれば Global 経由でもイケます。
これで負荷として事が足りることもありますが、中規模以上では心もとないので、通常は負荷試験としての一連の動作確認をするための構成としています。
N:1 ダイレクト型
次に1ホストに対して高負荷をかける構成です。User から、Client となる ECS Fargate を起動し、必要なインストールを行います。AWSリソースを操作するので、AWS鍵またはRoleを持つリソース上で実行します。
その後、User から全ECSでLocustを起動し、クラスタ構成で負荷試験を稼働させ、結果を取得します。
送信先は先程と同じく、任意のホスト1つになるので、1Serverにガッツリかけるなり、ALBや外部LoadBalancer経由で本番想定などを行います。
Master はただの司令塔&結果集計場所で、Worker が実際にリクエストを出す所です。複数ユーザー数で実行したとき、ユーザー数を分割する形でWorker達に処理が分散されます。
スペックとアプリケーションによりますが、10Workerあれば、10000~15000 RPS くらい発生させることができます。同時接続ユーザー数はLocustでの使用メモリ次第ですが、2~3万 以上動かせます。
補足としては……
UserからClientへの実行命令は ECS Exec を採用し、シナリオや結果データのやり取りは S3 経由で行っています。最初はSSH経由でどちらもやろうと考えましたが、通信経路の確保が必要になるので、より自由度の高い仕組みを目指した結果です。
Locustプロセスは1vCPUしか利用できないので、vCPU数に応じてWorker上には複数のLocustプロセスを自動的に起動する仕組みにしています。
あとSpot適用なので、サッと作ってサッと片付ければ費用はそう高くなりません。ってくらい。
M:N プロキシ分散型
最後は独自の工夫で、リクエストを分散する構成です。1つコンテナを余計に起動し、HAProxyとすることで、Workerからのリクエストを受けて複数のServerへ分散転送します。
わざわざこうした理由は、AWS内での負荷試験申請の条件を考慮したり、そもそもクラウドやLoadBalancer関係なく分散管理できるようにしたかったからです。LB経由だろうとProxy経由だろうと、メトリクスやAutoscalingなど負荷試験に影響はありません。
複数あるServerは、EC2やECSの任意のタグがついたリソースを対象とし、数秒間隔でチェックして haproxy.cfg を書き換えることで、リソース変動にも対処しています。また一応、タグ管理ではない任意のサーバーリストを指定できるようにもしてあります。
1つ弱点があるとすれば、ECS Fargate は sysctl を編集できないので(参考:タスク定義パラメータ)、同時接続数にそれなりの限界があることです。プロセスID的に、3万前後が上限になるので、それ以上の大量ユーザー数で行いたい場合はLB経由になります。
それでも、HAProxyも複数vCPUで稼働させる設定にすることで、10000 RPS以上をゆうに捌けるので、たいていの負荷試験としては十分でしょう。
自動化
以上の内容を、1つの外道式システムとしてまとめました。それにより、作業としては4つになっています。設定で構成選択や負荷条件などを調整し、あとは全てワンコマンドにしたので、細かくLocustクラスタやHAProxyを管理する必要なく、手元のポチポチだけで完了する流れになっています。
シナリオ関連はまた別の話ですが、ポチって2~3分でLocustクラスタができ、ポチって数秒で負荷リクエストが始まり、結果はAPI Gateway管理画面で見れ、終わったらポチってリソース全削除して終わり。という感じ。
なんかもう最近は便利な仕組みがありすぎて、こういう独自の仕組みを練り上げるにしても、ほぼ困ることなく効率化できてしまうので、凄い時代だなぁと思います。
本事例が参考になるかはわかりませんが、早めにこういう取り組みをしておくと、開発における負荷試験フェーズを短縮でき、エンジニアのストレス軽減にもなるので、大いに徳を積んだ手応えになります:-)