DNSラウンドロビンとmod_proxy_balancerによるWebサイトの負荷分散(案)

apache2.2と同時にリリースされたmod_proxy_balancerや、DNSラウンドロビンの設定にまつわる話はそれぞれ個別にいろんなところで記事にされているが、Webサーバの負荷分散システム全体としての種々の情報がまとまっている記事はそれほど多くない気がする。そこで、Web屋のネタ帳 on CNETの方で書いた チープなDNSラウンドロビンは高価なロードバランサの座を奪い返せるか という記事の続編ついでに書いてみる。

長々とした文章よりもよりも図解で一発!、ということで図を描いてみた。Webサーバーの負荷分散&冗長性の確保のための構成(案)。
200608dnsrr.png
注: わかりやすくするためにスイッチとかファイアウォールとかそういう細部は省略している。サーバーの負荷分散の話であってネットワークのそれの話ではないことにご留意。

上段のapacheがmod_proxy_balancerを使ったリバースプロキシ。The Netに繋がる側はグローバルIPアドレスを与えておき、全てwww.example.comというホストに対してDNSのAレコードを登録しておく(=DNSラウンドロビン)。 下段がWebサーバまたはAPサーバ。こちら側はすべてローカル用アドレス(192.168.*みたいな)でよい。 リバースプロキシが3つでwebサーバ4つとなっているが、単に例である。リバースプロキシ2台でWebサーバが10台とかでもなんでも、必要に応じて適宜考えるということで。

以下、要点をかいつまんで説明。

DNSラウンドロビンが障害を起こしているサーバ(上図で言うとリバースプロキシサーバ)のIPアドレスをブラウザに返してしまった場合の対処

前記事にあるとおり、 最近のブラウザは、DNSが複数のIPアドレスを返した場合に、HTTPアクセスが成功するまでその全てのアドレスに対して接続を試みるので問題なし。

障害で落ちてるwebサーバの切り離し(振りわけ対象から除外)

mod_proxy_balancerがやってくれる。詳しくは下記参照。

セッションの維持

ショッピングカートとかWebメールとかIDとパスワードでログインしてログアウトする、といったいわゆるセッション維持が必要なWebサイトの場合、Cookie上にあるセッションID(≒どのWebサーバがそのセッションを発行して維持しているのかがわかる値)をリバースプロキシが察知して、そのWebサーバにアクセスを振る必要がある。その点、mod_proxy_balancer(正確にはmod_proxy側?)の stickysession という機能がそれを担ってくれる。 詳しくは下記参照。 ただ、セッション情報の保存場所を一本化して外だしすることで、リバースプロキシがセッション振り分けする必要をなくす、という手法も考えておくべきだろう。PHPであればデフォルトでは/tmpディレクトリ配下にファイルの形でセッション情報が保存されるが、それを別のNFSサーバ上にマウントしたディレクトリにすることで複数のどのWebサーバであっても同じセッション情報を扱えるようにするとか。あるいはセッション情報の保存も外部サーバ上のデータベースかあるいはmemcachedとか。Tomcatであればクラスタリング(セッションレプリケーション)させてみるとか。

SSL

https://に対する処理はリバースプロキシ側でやることになると思う。ただし下位層でhttp、httpsどちらでリクエストされたかを知りたい場合(例えばログイン画面にhttpで来ちゃった場合はhttps://に強制リダイレクトさせるとか)には、ウノウラボ Unoh Labs: mod_proxy_balancer 小技集によると
httpd.confに
 RequestHeader set X-SSL-REQUEST %{HTTPS}s
とつけてあげると、 X-SSL-REQUEST というヘッダが入ります。 %{HTTPS}s の部分は apacheがSSLだと on と加えてくれますので、web側ではこのヘッダを見るのが良いかと思います。 X-SSL-REQUEST は自由に変更できるので、推測されにくい文字列の方がよいかもしれないですね
という小技が使えそう。

DNS設定

リバースプロキシサーバのIPアドレスを全てAレコードで設定。 また、DNSラウンドロビンという目的上、TTL(生存時間)をかなり短めに設定しておいたほうがいいと思われる
www  300  IN  A      202.xxx.yyy.zzz
www  300  IN  A      202.aaa.bbb.ccc
www  300  IN  A      202.ddd.eee.fff
みたいに。ちなみにwww.yahoo.co.jpも300(つまり5分)にセットされている。www.rakuten.co.jpでは60秒とさらに短い。 これはブラウザでyahooやrakutenにアクセスした後でコマンドプロンプトで ipconfig /displaydns をたたくとわかる。

DNSサーバ側でTTLを短くしても、中継するDNSサーバやクライアントPCでキャッシュされてしまうのはどうする?という話だが、SimpleFailOverというソフトを開発している会社の解説によるとつぎのようなことらしい。

  • 「DNSの変更がネット上に浸透するには24時間から72時間くらいかかる」ということがよく言われるが、これはドメイン名自体の登録での話である。なぜならDNSのrootサーバのTTL(生存期間)が24時間になっているからである(筆者注:これは資料が書かれた2004年の話。2006年現在はもっと短くなってるはず)。しかし www.example.comのような個々のドメインの配下では、好きなようにTTL値を設定できる。
  • メジャーなDNSサーバソフトウェアであれば指定されたTTL値のとおりに適切に扱うはずである。問題はコンパイルや設定の段階で特殊なことをしているDNSサーバだが、現在ではそのケースも減ってきている。
  • Windows2000、XP、Server2003上で稼動するMicrosoft Internet Explorer 6 は、DNSのAレコードをキャッシュしない。CNAMEレコードだけをキャッシュする。これは(Aレコードであれば)DNS設定の変更にブラウザが素直に追随してくれることを意味する。 (筆者注:Aレコードをまったくキャッシュしないというのはほんとか?という気がする。だがいずれにせよクライアント側のネットワーク上のDNSサーバがTTL値指定の時間だけキャッシュしていることに変わりはない)
  • 古いWindows(95,98,Me)で動くInternet Explorer 4,5,6 については、すべてのDNSレコードはそのTTL値にかかわらず30分間キャッシュされてしまう。
  • FirefoxとMozilla/Netscapeは全てのDNSレコードはそのTTL値にかかわらず1分間キャッシュされる。(もっと古いバージョンだと15分)
以上、DNS Caching and how it affects Simple Failover(2004年9月)より抜粋&訳。なお、調べていたらたまたまこの資料に行き着いたので紹介しているだけであって、SimpleFailOverという製品そのものについては筆者は調べてないし言及しないのであしからず。 また、ブラウザではなく企業や学校などでよく使われているプロキシサーバ(squidとか)だとどうなるのかという話はこの資料にはなかった。日本の携帯電話ブラウザだとどうなるという話ももちろん無い。

なお、もしもリバースプロキシの1台がトラブルで落ちてその状態が長時間続く場合には、DNSの設定からそのIPをはずすという運用をとったほうがいいだろう。

以上はすべて机上での設計であり実際に組んでテストしたわけではない。 がしかし、この業界のベンチャー企業ではめずらしくない構成ではないだろうか。 と思っていたらnaoyaのはてなダイアリー - Apache 2.2.0 + mod_proxy_balancerという記事をみつけた。もうちょっと詳しい話希望 >はてなの中の人。

see also:
cyano: mod_proxy_balancerで中〜大規模サーバー運用するときの勘所 - (1) mod_proxy_balancerの設定編

追記:
普通のlinuxマシンをLVSで冗長化。数百万円のロードバランサの代わりになる

トラックバックURL

このエントリーのトラックバックURL:
http://www.ywcafe.net/mt/mt-tb.cgi/623