サーバ負荷分散概論
出典: KLablabWiki
- タイトル
- サーバ負荷分散概論
- 著者名
- KLab(株) ひろせ まさあき HIROSE Masaaki
- 初出
- 技術評論社刊『WEB+DB PRESS Vol.37』
目次 |
特集のはじめに
本特集のメインテーマは『サーバ負荷分散』です。 負荷分散というと
- むずかしそう
- 機器が高価
- 大規模向け
というイメージが先行して、敬遠している人は多いのではないかと思います。
実は、今回の特集はそんなあなたのために書きました。 本特集を読み終えたあと、きっとその印象は
- おもしろそう
- 安い
- 手軽に使える
に変わっているでしょう。
ではではさっそく本題に入りましょう。まず本章では「サーバ負荷分散」一般についてざっと説明し、次章以降でより具体的な実現方法を解説していきたいと思います。
なぜサーバ負荷分散をするのか?
『サーバ負荷分散』[1]をひとことでいうと、「1つのサービスを複数のサーバで行うこと」です。では、どうして複数のサーバでサービスしたいのでしょうか? どんな利点があるのでしょうか? 大別するとそれは2つあります。[2]
性能
まず1つめの利点は性能向上です。
例えば、100人にサービスできる性能を持ったサーバが1台あるとします。これを200人にサービスできるようにするにはどうすればよいでしょうか。
方法その1は、倍の性能を持ったサーバを導入する、です。既存のサーバを取り替えるだけなので、導入も比較的容易です。このように、サーバの単体性能を上げてシステム全体の性能を上げることを『スケールアップ』といいます。
方法その2は、100人にサービスできるサーバをもう1台導入して2台でサービスする、です。これが今回のテーマのサーバ負荷分散で、このように、複数台のサーバを並べてシステム全体の性能を上げることを『スケールアウト』といいます。
導入の容易さという観点で比較すると、スケールアップよりスケールアウトの方が難しいです。なぜなら、複数サーバにサービスを振り分ける装置(ロードバランサとか負荷分散装置といいます)が必要になったり、サービスを提供するアプリケーション(Webアプリなど)も場合によっては分散環境を意識した作りにしたりする必要があるためです。
ここまで読むと、スケールアップのほうがよさそうに思えるかもしれませんが、最近のWebサービスは安価なサーバを大量に導入してスケールアウトする構成が主流です。最も有名なのはご存じGoogleですね[3]。
Webサービスでスケールアウトが好まれるのは、ユーザ数やサービス規模の予測がしづらいため、必要にあわせて段階的に設備投資をしたいというWebサービスならではの特性があるためではないかと思います。
可用性
利点の2つめは可用性の向上です。
日常あまり聞きなれない言葉ですが、「可用性が高い」というと、そのシステムが提供しているサービスは滅多に止まらない、という意味になります。また、可用性のことをアベイラビリティ(availability)といったりもします。
苦い思い出がある方も多いと思いますが、サーバは壊れます。いくら高くていいサーバだとしても、かたちあるものいつかは壊れます。諸行無常です。
200人にサービスできるサーバでも、それが壊れたら一切のサービスが停止してしまいます。これがもし100人のサーバが2台ならば、片方壊れてもシステム総体としての性能は半分になりますが、なんとか全停止からは免れます。
「サーバはなるべく壊れないようにいいものを」と考えている方は多いのではないかと思いますが、ここで発想を転換して「サーバは壊れるものだからしかたない」と考えると、スケールアップよりもスケールアウトのほうがいい、更にいうと、少数の高価なサーバよりも大量の安いサーバでスケールアウトしたほうがいいという結論に辿り着くと思います。
なぜなら、数台の高価なサーバのシステムよりも数十台の安いサーバのほうが、1台のサーバが故障した場合のシステム総体の能力低下が小さいからです[4]。
これも安価な大量のサーバでのサーバ負荷分散が好まれる理由ではないかと思います。
サーバ負荷分散の実現方法
サーバ負荷分散の必要性が理解いただけたところで、では、どういう仕組みで負荷分散をするのか、について述べたいと思います。
サーバ負荷分散を実現するにはいくつか方法があるのですが、その代表的なものを2つ紹介します。
DNSラウンドロビン
DNSラウンドロビンとは、DNSを使って1つのサービスを複数台のサーバに分散する構成です。
仕組みはいたって簡単で、名前は同じでIPアドレスが異なるAレコードを複数、DNSサーバに登録するだけです。(図1)
追加機材や複雑な設定が必要なく、DNSのゾーンファイルを変更するだけで実現可能なのでお手軽というメリットはあるのですが、次のような欠点があります。
- 均等に分散されるとは限らない
- どのサーバに分散されるかは、クライアントが名前を引いた結果のAレコードの順番に依存するので、分散の均一性の保証や重みづけを制御することができません。また、DNSのキャッシュサーバがクライアント側のネットワークにあったり、OSにキャッシュ機能が搭載されていたりする場合、キャッシュが切れるまで同じAレコードのサーバにアクセスし続けることになり、これも均等に分散されるとは限らない一因となります。
- サーバ障害に弱い
- サーバに障害が発生してサービス不能になっても、当然ながらDNSサーバにはそれを検知する仕組みがないので停止しているサーバのAレコードを返答してしまいます。 たとえ、障害を検知して自動的にAレコードを変更する監視プログラムを作ったとても、DNSのTTLが切れるまでは変更が波及しません。TTLを短くしても[5]波及までの時間差をゼロにすることはできないので、障害に弱いといわざるを得ないでしょう。
まとめると、冒頭で挙げた「スケールアウト」も「可用性の向上」もDNSラウンドロビンでは完全には実現できないわけです。
コラム
サーバ負荷分散で、本当にDNSは役立たずなのか?
DNSの使いどころの1つとして、GSLB(Global Server Load Balancing)があげられるのではないかと思います。 GSLBとは、SLBが単一拠点内で完結する負荷分散であるのに対して、地理的に異なる拠点間で負荷分散することをいいます。大きな目的としては次の2点があります。
- ある拠点がサービス不能になった場合の可用性の確保。
- ネットワーク的に近い拠点へ分散し、応答性を高める。
まともにGSLBをやろうとすると、拠点間のロードバランサ同士の連携や、近隣探索などいろいろと大変です。 そこでDNSの出番です。仮に「データセンタが天災などでまるごと使用不能になることはそうないだろうし、そんなときはDNSレコードの変更波及の遅延ぐらい許容できる」と割り切れるのであれば、あくまで簡易的なGSLBですが、DNSを利用したアクティブ/アクティブ(DNSラウンドロビン)構成やアクティブ/バックアップ(Aレコードの切り替え)構成もアリなのではないかと思います。
ロードバランサ
本特集のメインテーマはこれです。
ロードバランサ[6]という専用の装置を導入します。クライアントからのアクセスはまずはロードバランサが一手に受けて、ロードバランサが適宜、サーバに振り分けてくれます。
この「適宜」というのがミソで、
- 重みづけをするなど分散方法を制御できる
- サーバが停止していたら負荷分散対象から外す
といったことができます。
また、一般的にロードバランサと呼ばれるものは、最低限、レイヤ4(L4)つまりTCPの層の情報(IPアドレスやポート番号)を元に分散することができるので、Web(HTTP)だけではなく、メール(SMTP)やMySQLなどのサービスも分散できる汎用的なものです。
分散機能以外で、DNSラウンドロビンと決定的に違う点をあげると、サービス用のグローバルIPアドレスが1つでいい点です。DNSラウンドロビンの場合はラウンドロビンする分だけグローバルIPアドレスが必要です。一方、ロードバランサの場合は、バーチャルIPアドレス(VIP)と呼ばれる仮想的なサービス用のアドレスが1つあればサーバ負荷分散ができます。つまり、サーバが数十台でも数百台でもグローバルIPアドレスは1つで済むわけです。
ロードバランサのいる構成
ロードバランサを配置した構成はいくつかのパターンがあるのですが、まずは概観をつかめるように、ここではいちばん基本的な構成を示しつつ、サーバ負荷分散の話でよく出てくる用語の説明もしたいと思います。
基本的な構成とその構成要素
おそらくみなさんにいちばんなじみの深いWebサービスを、ロードバランサを使って負荷分散する構成を図2に示します。これを見ながらリクエスト/レスポンスの流れを追ってみましょう。
まず、クライアントがhttp://example.org にアクセスします。example.orgをDNSで引くとそのIPアドレスは10.0.0.100とわかるので、クライアントは10.0.0.100のポート番号80に接続します。ここまでは負荷分散環境であろうとなかろうと同じです。
さて、この10.0.0.100というサービス用のIPアドレスはロードバランサに割り当てられています。つまり、まずはロードバランサがすべての接続を受け付けるわけです。そしてこのようなサービス用のIPアドレスをバーチャルIPアドレス(VIP)といいます。
続いて、パケットを受け取ったロードバランサは、VIPに対応づけられたサーバ群のどれかにクライアントからのパケットを転送します。このサーバ群のことをバーチャルサーバグループ(VSG)といい、個々のサーバをリアルサーバと呼びます。また、VIPと対比して、リアルサーバのIPアドレスをリアルIPアドレス(RIP)と呼んだりもします。
このようにロードバランサはリアルサーバのどれかにリクエストを転送するわけですが、転送先のリアルサーバを選出する際のアルゴリズムにはいくつか種類があります。ロードバランサの実装によって対応しているアルゴリズムは異なるのですが、典型的なものをいくつか紹介します。
- round robin
- 最初に来た接続はリアルサーバ(1)に、次に来たのはリアルサーバ(2)といった具合に、グループ内のリアルサーバに順番に分散します。
- least connections
- グループ内で、既に開かれている接続の数が少ないリアルサーバに分散します。
- hash
- 接続元IPアドレス、もしくは、宛先IPアドレスのハッシュ値に応じてリアルサーバに分散します。接続元IPアドレスのハッシュを採用した場合、同じクライアントからのリクエストは同じリアルサーバに分散されるようになります。
また、ロードバランサはリアルサーバの死活監視も行っていて、ダウンしているとみなされたリアルサーバは自動的にバーチャルサーバグループから外され、復旧するまでは分散対象になりません。このような死活監視をヘルスチェックといいます。ヘルスチェックの方法もロードバランサの実装によって異なるのですが、よく使われるものを紹介します。
- ICMP
- pingコマンドと同じようにICMP Echo Requestパケットを送って、Echo Replyが返ってきたら生きているとみなします。 しかし、リアルサーバがサービス用のポートで接続を受け入れられる状態かどうかはICMPでは確認できまん。 また、OSはハングアップしているがpingには応答できる状態は、ICMPでは生きているとみなされてしまいます。
- TCP
- リアルサーバのサービス用のポートにTCP接続をして、そのポートが開いていれば生きているとみなします。ポートが開いているかどうかの確認だけなので、プロトコルに応じたレスポンスがちゃんと返ってくるかどうかは確認できません。
- protocol
- TCP接続した上で、HTTPやSMTPなどのやりとりをし、期待したレスポンスがあれば生きているとみなします。例えばHTTPならば、リアルサーバにHTTP GETして、その応答が200 OKならば生きているとみなす、といった具合です。
話を負荷分散にもどしましょう。ロードバランサからリアルサーバに転送されたHTTPリクエストは、リアルサーバのWebサーバプロセスで処理され、レスポンスを返します。
返りのパケットは来たときと同じようにロードバランサを経由してクライアントに返す構成と、ロードバランサを経由せずにリアルサーバがクライアントに直接返す構成とがあります。特に後者の手法はDirect Server Return(DSR)と呼ばれ、返りのパケットの面倒をみなくていい分、ロードバランサの仕事が減るので、単位時間あたりのさばけるパケット数の増加が期待できます。
ここではリクエスト/レスポンスのおおまかな流れを説明しました。細部についてはのちほど解説しますので、ここではパケットの流れと用語をおさえてもらえば大丈夫です。
ロードバランサはなにを元に分散するか
さきほど「VIPとVSGを対応づける」と書きました。では具体的に、どういう情報を元に対応づけているかという点について解説したいと思います。これから述べることは、ロードバランサがどこまでパケットを解析するか、ということにもなり、分散決定だけでなく、セッション維持管理などにも関係してきます。
さて、この観点でロードバランサを大分類すると、
- レイヤ4(L4)ロードバランサ
- レイヤ7(L7)ロードバランサ
の2つになります。「レイヤ」とはOSI参照モデル[7]由来のことばで、レイヤ4はトランポート層といい、TCPやUDPが対応し、レイヤ7はアプリケーション層といい、HTTPやSMTPなどが対応します。
L4 ロードバランサ
L4 ロードバランサはTCPやUDPの情報を元に分散決定します。つまり、
- 始点IPアドレス
- 終点IPアドレス
- 始点ポート
- 終点ポート
が使える情報となります。
たいていのロードバランサが持っている基本的な機能です。L4まで解析することにより、
- IPアドレス(VIP)とポート番号を元にしてリアルサーバに分散する
- 始点IPアドレスを元にしてリアルサーバに対する分散を固定化する
といったことが可能になります。
L7 ロードバランサ
L7 ロードバランサはHTTPやSMTPといったプロトコルの中身まで解析対象にします。 HTTPを例にすると、リクエストURLやUser-Agentヘッダ、Cookieをも解析することができ、
- URLのパスを元にしてリアルサーバに分散する
- CookieにリアルサーバのIDを埋め込み、それを元に分散を固定化する
といったことが可能になります。
このようにプロトコルに応じた柔軟な対応ができるメリットはあるのですが、ロードバランサはクライアントからのパケットを溜めてペイロードを解析して、またそれをリアルサーバに転送する必要があるので、来たパケットをじゃんじゃん転送すればよいL4ベースの分散に比べると、より負荷は高く、(パケットを再構成するので)処理能力も落ちます。
また、プロトコルデータを解析するという観点では、L7 ロードバランサはリバースプロキシとあまりかわらないということもできるでしょう。実際、以下にあげるような「リバースプロキシ兼ロードバランサ」とうたったプロダクトがいくつかあります。
- HAProxy
- mod_proxy_balancer
- Perlbal
コラム
LVSとL7ロードバランサ
LVSと関係が深いL7ロードバランサのプロジェクトがいくつかあるので紹介します。
- KTCPVS
- http://www.linuxvirtualserver.org/software/ktcpvs/ktcpvs.html
- 残念ながら2004年を最後に更新されていないようです。
- UltraMoneky*L7
- http://sourceforge.jp/projects/ultramonkey*l7/
- 2005年にNTTコムウェアが発表した実装です。
- Linux L7SW
- http://www.linux*l7sw.org/
- 生まれたばかりのプロジェクトですが、今後、要注目です。
なぜロードバランサを導入しないのか?
ここまででサーバ負荷分散やロードバランサ一般のお話は一段落です。さて、読者の方はこんなにステキなロードバランサを導入しない手はないと思った方も多いのではないかと思います。しかしながら、比較的大規模で人気のあるサイトでも、ロードバランサを導入していなかったりするようです。
なぜロードバランサを導入しないのでしょうか?
難しそう
「なんとなく難しそう」という声をたまにきくのですが、これはあまりロードバランサに触れる機会がないためで、決定的な導入障壁ではないのではないかと思います。
費用面
技術的困難さよりも、この費用的な面が導入障壁になっているのではないかと思います。
ロードバランサのアプライアンス製品となると、ミドルレンジの製品でその価格は数百万円のオーダになります。ロードバランサの二重化も考えると費用はこの2倍になります。更に保守費用などランニングコストもかかるので、総合すると結構な金銭的負担がかかることになります。
実際に、技術力もありガッツも勢いもある某社でも、ロードバランサがあまりにも高価なため、費用対効果が低いという結論になり導入していなかったという話をききました。
Linuxベースのロードバランサ
導入したいけどそんなにお財布に余裕がない人はロードバランサをあきらめるしかないのでしょうか? 否!! そんな方にこそ本特集のメインテーマであるLinux Virtual Server(LVS)をおすすめします。
LVSとは?
Linux Virtual Serverとは、Linuxで高性能かつ高い可用性をもったサーバシステムを作ろうというプロジェクトです。
そしてLVSの成果物の1つにIP Virtual Server(IPVS)というものがあり、IPVSを使うことにより、LinuxをL4ロードバランサにしたてあげることがきます。IPVSはすでにバージョン2.4と2.6のカーネルにマージされているので、カーネルにパッチを当てたりする必要もありません。
LVSのいいところ
筆者らは、以前はハードウエアベースのロードバランサを使っていたのですが、数年前にLVSに乗り換えました。今のところL4ロードバランサとしてトラブルもなく大満足なのですが、特によかった点をあげてみます。
金銭的コストがゼロ
Linuxベースなので、PCのハードウエア費を除けば金銭的コストはゼロです。
単純にお金がかからなくなってうれしいというのもあるのですが、おかげで
- 内部ロードバランサ
- 外部向けのロードバランサとは別に、内部にもロードバランサを配置して、内部サーバ間のSMTPやリバースプロキシといったアクセスも(冗長化目的で)負荷分散しています。
- 開発環境にもロードバランサ
- プロダクション環境と同じように、社内にある開発環境にも外部/内部のロードバランサを配置して、分散環境下でのテストもできるようにしています。
といったことも実現できました。
全部見える
Linuxなので全部見られます。
たとえば、ロードバランサを経由するパケットはtcpdumpやetherealなどで眺めることができるので、動作を確認する際やトラブルシューティングのときにとても助かります。
また、ロードバランサの動作としてなにかおかしい挙動があっても、ソースコードがあるので(がんばれば)原因を突き止めることもできます。[8]
次章以降では
LVSのおかげでロードバランサ導入の金銭的障壁は解消されました。
残るは「なんとなく難しそう」です。
この障壁を解消すべく、続く第2章ではLVSを使ったLinuxベースのロードバランサの具体的な作り方を、第3章では負荷を分散するロードバランサ自身が故障した場合の対応について紹介します。
脚注
- ↑ SLB(Server Load Balancing)ともいいます。
- ↑ 「負荷分散」はその名の通り負荷を分散することを指す言葉なので、2つめの利点である「可用性」や「冗長性」という意味は含みません。 しかし、ほとんどのロードバランサは可用性向上の機能をもっているのと、『サーバ負荷分散』という言葉を使う際は、「可用性」も含意することが多いので、ここでは「可用性」も「サーバ負荷分散」の利点としてあげました。
- ↑ Computer History Museumに寄贈されたGoogleの初期サーバが次のURLで見られます。 http://www.computerhistory.org/core/exploration/explore02.html http://bb.watch.impress.co.jp/cda/alphageek/11461.html
- ↑ その反面、サーバの台数が多いので、「いずれかのサーバが故障する確率」は大きくなります。
- ↑ TTLを極端に短くすると、「誕生日攻撃」の被害を受けやすくなるというリスクもあります。 http://www.st.ryukoku.ac.jp/~kjm/security/memo/2006/12.html#20061212_DNS
- ↑ 負荷分散装置、負荷分散機ともいいます。
- ↑ OSI参照モデル http://ja.wikipedia.org/wiki/OSI%E5%8F%82%E7%85%A7%E3%83%A2%E3%83%87%E3%83%AB
- ↑ ハードウエアベースのロードバランサはブラックボックス的な部分が多いので、明らかにロードバランサ起因の不思議挙動が発生しても、原因も調べられず結局リセットして復旧したとか、エンジニアとしては大変歯痒い体験を幾度となく経験しました…

