大規模トラフィックを捌くための CloudFront 以外の選択肢
〜 大晦日に秒間 1 万ユーザを捌くためにやったこと (ロードバランサー編) 〜
今回、ロードバランサーは全面的に AWS の Elastic Load Balancing (ELB) を使用しました。
Web API を提供するシステムにはもともと ELB を使う予定だったのですが、静的ファイルの配信などは ClouldFront + S3 という構成でいこうと思っていました。
が、最終的には静的ファイルを配信するシステムも ELB + EC2 という構成になりました。
そのへんの経緯とか、AWS を使うときのシステムのフロント周りの負荷分散にはどういう選択肢があるのかとか、軽くまとめてみようと思います。
静的ファイルの配信には CloudFront を使ったほうがいいのか
CloudFront は S3 と併用することで、静的なファイルの配信のことはほとんど考えなくていい、というくらい簡単にファイル配信の仕組みが構築できます。
しかし、想定するリクエスト数や転送量によっては、他の方法でファイル配信システムを構築したほうがよいことがあります。
とくに大規模なトラフィックが想定される場合には、一度 AWS のサポートセンターに相談してみることをおすすめします。
今回は、1.3 MB ほどのすこし大きめの単一のファイルに、秒間 10,000 リクエストが押し寄せてきても耐えられるシステムを構築する必要がありました。
転送量にして 104 Gbps です。
そこで、サポートセンターに相談したところ、CloudFront を使うのではなく以下の 2 つのいずれかの方法をとることを勧められました。
S3 に異なる名前の同一のファイルを複数置いてランダムアクセスさせる
EC2 インスタンスを複数台立ち上げておいて ELB でアクセスを分散させる
S3 に異なる名前の同一のファイルを複数置いてランダムアクセスさせる
これは、S3 に同じファイルを多数置いておき、クライアント側からアクセスが各ファイルに分散するようにしてあげるという方法です。
こうすることでファイル 1 つだけの場合よりも S3 のパフォーマンスをあげることができます。
S3 バケット内のオブジェクト達は、負荷分散のため、オブジェクト名をもとに物理的に離れたサーバにパーティショニングされて配置されるようになっています。
このような仕組みの上では、たとえば 1 つのオブジェクトへのアクセスが急激に上昇した場合、そのオブジェクトが配置されている単一のパーティションのみがアクセスをうけることになります。
なので、異なる名前の同一のファイルを多数用意して S3 に置いておき、クライアントからランダムアクセスしてあげるようにすることで、各パーティションにアクセスを分散させることができ、パフォーマンスを上げることができます。
(より効果的なオブジェクト名のつけ方については、Amazon S3のパフォーマンスをあげるコツ が参考になります。)
で、実際にどのくらいのファイル数を用意すればよいのかということについてですが、Amazon S3のパフォーマンスをあげるコツ を見たりするに、各ファイルへのリクエストが 50 ~ 100 req/s くらいに収まるくらいの数を用意するのがいいのかなと思います。
今回は、先ほども触れた 1.3 MB の単一のファイルを配信するシステムで、10,000 req/s を捌く必要がありました。
というわけで、サポートセンターからも各ファイル 50 req/s くらいになるように 200 ファイル程置いたらいいよ、というアドバイスをうけたりしました。
今回はクライアントサイドの都合でランダムアクセスが難しかったのでこの方法がとれませんでしたが、特定のファイルにアクセスが集中するような場合には有効な方法だと思います。
EC2 インスタンスを複数台立ち上げておいて ELB でアクセスを分散させる
こちらは静的ファイル配信用の EC2 インスタンスを多数立ち上げておいて、ELB でバランシングさせる方法で、今回はこっちでやりました。
Auto Scaling Group などを使うことでインスタンスの管理も比較的簡単です。
ただし、急激なトラフィック増加が想定される場合には、事前に ELB の Pre-warming 申請をしておく必要があります。
「急激なトラフィック増加」とはどのくらいの増加なのか、ということですが、「5 ~ 10 分で 20% 以上のトラフィック増加」というのが目安らしいです。
(Pre-warming 申請とは何ぞや?という人は、同時大量アクセスに備えて ELB を Pre-wariming 状態にしておく を参照)
なので、それと同程度かそれ以上の増加率が想定される場合には、Pre-warming 申請をしておくと安心できます。
Pre-warming 状態の ELB でも対応できない場合
ただし、想定するリクエスト数や転送量によっては、Pre-warming 状態でも 1 つの ELB で対応できるトラフィックを超えている場合があります。
その場合は、Pre-warming 状態の ELB を複数用意し、DNS ラウンドロビンを設定しておくという方法があります。 これも Route 53 を使うことで簡単に設定できます。
(設定手順は、Pre-warming した複数の ELB を Route 53 で DNS ラウンドロビンする にまとめました。)
今回は、1.3 MB 程度の単一のファイルを配信するためのシステムが ELB 1 つで対応できる転送量を超えているということで、この方法をとりました。
Pre-warming 状態の 1 つの ELB に対するトラフィックが、HTTP リクエスト数にして 200,000 req/s、転送量にして 40 Gbps 程度に収まるようにということで、ヴァージニア、オレゴン、アイルランドの各リージョンに分散させて配置しました。
ちなみに、Web API を提供するシステムは、HTTP リクエスト 30,000 req/s、転送量 120 Mbps の想定だったので、Pre-warming 状態の ELB 1 つで問題ありませんでした。
とここまで書いといてなんですが、実際にどの方法をとるかを決める際には、AWS のサポートセンターに相談してみるのがいいかと思います。
自分も AWS のサポートセンターにいろいろ助けてもらったおかげで、お正月は笑って過ごすことができました。