一般的な Web Application というのはロードバランサ、Webサーバ、アプリケーションサーバという HTTP を喋るサーバで構成されていると思います。
ロードバランサは高級なハードウェアからソフトウェア(lvs, httpd, etc..)で作るものまで色々ありますね。
アプリケーションサーバでは各種言語に合わせた実装でデーモンが常駐してるでしょう。これはいわゆる普通の Web サーバよりは単純なコンテンツを返す性能が低いです。
そんなわけで動的なアプリケーションサーバが有る構成では js や css や画像など静的なファイルは Apache や nginx などの専用の Web サーバでサービスして、動的なリクエストだけバックエンドのアプリケーションを返す構成を取ります。
構成としては
構成A +---------------+ | reverse proxy | +---------------+ /\ / \ / \ / \ +--------+ +---------+ | static | | dynamyc | +--------+ +---------+とか
構成B +------------------------------------+ | static contents with reverse proxy | (Web Server) +------------------------------------+ | +------------------+ | dynamyc contents | (application server) +------------------+のような二通りの構成が取れると思いますが、このエントリでは後者のシンプルな方で話を進めます。
そして冗長性を考えると、それぞれのパーツが1台づつで運用されてるとかマジありえないので普通のサービスの最小セットは以下のようになります。
構成C +----------+ +----------+ | balancer | | balancer | +----------+ +----------+ | \ / | | \/ | | /\ | | / \ | +----------+ +----------+ | web | | web | (Web サーバ) | | | | | | | app | | app | (アプリケーションサーバ) +----------+ +----------+
上の構成の場合だと app が落ちたら前段の web が 502 を返してしまって、折角 balancer が良い感じにバランシングしてくれてるのに可用性が下がってしまいます。
注意深く balancer をセットアップしていれば、 app のダウンを検知して故障のある app を抱えてる web をはずす事は出来ますが, 検知に時間はかかるし構成にかかる設定が複雑になります。
特にアプリケーションサーバの再起動を伴う作業の時に一瞬止まったりする可能性のあるアプリケーションサーバを使った場合には、再起動のたびに 502 を連発してしまってダウンタイム多発になります。
(この問題は近代的な環境である Unicorn や Server::Sterter などを使う事によりホットデプロイで対応可能になっています。)
この問題を解決する手段としては web と app の間で更で以下のようにしてバランシングしてあげるという事です。
構成D +----------+ +----------+ | balancer | | balancer | +----------+ +----------+ | \ / | | \/ | | /\ | | / \ | +-----------+ +-------------+ | web (A) | | web (B) | (Web サーバ) +-----------+ +-------------+ | \ / | | \/ | | /\ | | / \ | +-----------+ +-------------+ | app (A) | | app (B) | (アプリケーションサーバ) +-----------+ +-------------+ # web (A) と app (A) ならびに web (B) と app (B) はそれぞれ同一インスタンスweb サーバが Apache だったり nginx だったりする時は、良い感じにバランシングしながら後ろの web サーバに reverse proxy する方法があるので捗ります。
ただしこの手法でもバランシングの設定が必要になるので、サーバクラスタに web(C) app(C) を追加して balancer で web(C) を追加して満足して httpd.conf などに app(C) を追加し忘れて分散してるつもりが負荷が偏る悲しい問題も発生し得ます。
httpd.conf にちゃんと追加さえすれば、同じサービスの全部の設定は一度書けばかってにバラまかれて良い感じに再起動されるので balancer 側で頑張るよりはだいぶ柔軟な運用ができるがそれは後ほど。
たとえば JSON API しかサービスしないよ!っていうケースの場合は静的コンテンツをサービスする為の Web サーバが実質不要になるため balancer と app だけの以下の構成を取るかもしれません。
構成E +----------+ +----------+ | balancer | | balancer | +----------+ +----------+ | \ / | | \/ | | /\ | | / \ | +-----------+ +-------------+ | app (A) | | app (B) | (アプリケーションサーバ) +-----------+ +-------------+ # web (A) と app (A) ならびに web (B) と app (B) はそれぞれ同一インスタンスこれの構成だと致命的な問題としてアプリケーションサーバの根っこの設定を変えたいとかで、ホットデプロイ不可能な再起動したい時に balancer 側を相殺してバランシングからはずさないといけないときに面倒いのです。最初から考慮した運用してれば大丈夫なのかもですが。
むりやりまとめると構成Dがいちばん安定するという結論に今なってます。
メリットとしては
ぼくみたいなしろうとが書いてると机飛んで来そうでこわいけどがんばってかきました><
Posted by Yappo at 2013年06月07日 19:34 | TrackBack | tech