スケールアウトの基礎的な考え方
WEBアプリケーションをスケールアウトする、あるいは大規模サービスを構築するときに、どう考えてサーバーを増やしてゆくかをまとめてみました。
この記事はインターン向けに社内Confluenceに書いていた基礎知識ドキュメントをどうせなら一般公開しようというシリーズの記事です。
そもそもスケールアウトとはなんぞや?
WEBアプリケーションで大規模なアクセスを処理する解決策としてサーバーを増やす事を「スケールアウト」といいます。
大規模なアクセスを処理する他の選択肢として、サーバーそれぞれのスペックを上げることは「スケールアップ」といいます。
ちなみに大きく展開をしたり、大規模にする概念そのものを「スケール」といい、「事業をスケールする」というような使い方がされています。
スケールアウト サーバー構成構成モデルの紹介
1番小さな構成、スケールアウト前の状態
一つのサーバー上に WEBサーバー / DBサーバー / アプリケーション(PHP)/ ストレージ / KVS など様々なミドルウェアを搭載して1サーバーで運用している状態を最初の状態として考えます。
1サーバー上で多くの機能(ミドルウェア)を動かしサービスを運営していると、メモリ・CPU使用率その他リソースに無理が出てきます。
そこでそれぞれの機能(ミドルウェア)を別サーバーで運用するというのが最初の考え方です。
ミドルウェアをそれぞれ別サーバーで運用している構成
各ミドルウェアをそれぞれ別サーバーで運用している状態がこちら
さらにアクセスが増えた場合、1機能1サーバーであるこの状態から、1機能多数サーバーの状態を作っていくことになります。
各機能のサーバーが複数台ある構成
各サーバーを増やした状態がこちら、この構成は1例です。
WEBサーバーへの不可を分散させる仕組みとしてスイッチがWEBサーバーの上流に出てきています。
他にもDNSラウンドロビンといったアクセス分散のシステムがあります。
将来スケールアウトさせるサービスを作るときに注意すること
スモールスタートで初期投資を抑えて、段階的にスケールアウト投資を行いサービスを大きくするという事例はよくあると思います。
ところが、いざスケールアウトに望むとなるとスケールアウトを考慮していない作りになっていて改修に莫大な工数がかかるという事例もよく聞かれます。
では何を考慮すれば将来のスケールアウト時に困らないのか?もちろんケースバイケースなのですが、以下に考慮すべき点の概要を思いつく限りあげておきます。
- ミドルウェアの接続設定を設定ファイルにまとめる、コード中にベタ書きしない
- 疎結合のシステムを意識する : DB設計リレーションとかあまりガチガチにするとDB分割できなかったり
- 重要:アプリケーションサーバーが複数になった時に起こることを考えておく
- セッションが複数サーバーで利用できるようにする or セッションが張られたサーバーに常にアクセスされるようにする
- memcached でセッションのデータを管理するとか、アプリケーションサーバーの外でデータ管理すると複数サーバーまたがるセッションが実現できます
- mod_jk とかセッションに紐付いたアプリケーションにロードバランシング中でも常にアクセスさせる仕組みがあります。
- WEBアプリケーション上でアップロードされるコンテンツを別途ストレージサーバーに保存する ※うっかりアプリケーションサーバー上に保存すると、データにアクセスできたりできなかったりする状況におちいります。
- ローカルのファイルを書き換えて処理の制御をする時は注意:ロックファイルとか意味をなすか考えよう?
- キャッシュの種類とキャッシュ場所に注意:ローカルメモリにキャッシュすると高速ですがそのアプリケーションサーバー上でしか利用できません、memcachedなど外部にキャッシュすると複数のアプリケーションサーバー上からキャッシュが利用できます。
- セッションが複数サーバーで利用できるようにする or セッションが張られたサーバーに常にアクセスされるようにする
処理量の増加以外のスケールアウトのメリット
帯障害性
HDDは壊れるもの、24h可動のサーバーでHDD RAID5構成の場合、平均2年でHDD障害が出てきます(9年自社サービス サーバー15台を運用していた体感値)。
他にも天災、論理的にデータが壊れる、うっかり削除してしまう等々障害が起きた時にそのサーバーを切り離せばサービスの停止タイムを最低限にサービスを再開することができます。
段階的スケールアウト、その考え方
実際にはいきなりすべてのサーバーを分離する必要はなく、必要に応じてサーバーを増やしていくことになります。
どんな時にどうサーバーを増やしてゆくか、簡単に思いつくものをあげておきます。
- SQLのレスポンスが遅い、処理が重い:DBサーバーを分離
- それでもinsert update 系クエリが遅い:master / slave を分離 select の負荷を分離する
- select 系クエリが遅い:slaveの台数を増やす
- それでも select が遅い:水平分割・垂直分割の検討
- それでも select が遅い:積極的にキャッシュを行ってそもそものSQL発行回数を減らす
- アプリケーションサーバー部分、プログラムの実行が重い:アプリケーション・サーバーを増やす
- この時WEBサーバーと必ずしも分離する必要、スイッチを用意する必要はありません、proxyサーバーを上流に立てて裏のアプリケーションサーバーを分散させたり方法はいろいろ
- SSLなどユーザーとの通信コストが重い:WEBサーバーとアプリケーションサーバーの分離
クラウドとスケールアウト
AWSの登場でスモールスタートからのスケールアウトといえばクラウドという雰囲気が流れていますが
必ずしもAWSが最適解でないと感じています。
AWSのすごいと思うところ
- 完全にAPI化されていて、分単位・数十秒単位でサーバーを増やして負荷に対応できる。
- SQL / ストレージなど スモールスタート、スケールアウトで工数が発生しない仕組みがある
AWSのデメリットだと思うところ
- 習得コストが大きい
- 同程度の処理をさばく構成をVPSや物理サーバーと比べた場合コストが高くなることが多い
- AWSと密結合になってしまい、他の環境でサービスを動かしにくい
分単位でアクセス負荷増加に自動的に対応しなければならない場合、現状クラウドサービスが唯一のソリューションだと思いますが、そうでない場合環境コピー機能のあるVPSで数時間で手動対応することが可能となってきています。
割安にスモールスタートでサービスを初めて徐々に増加するアクセスに対応するのであればVPSがよいソリューションなのではないかなと感じています。