最終更新日: 2014年1月13日
Squid Home / FAQトップ

冗長化への考察

1. DNSによる冗長化

Proxyの冗長化奉納で真っ先に思い浮かぶのは、プロキシサーバを複数台用意しておき1台が停止しても他のプロキシで代替えする方法でしょう。
この方法で検討する必要があるのは、如何にして各ユーザのクライアント環境に影響を与える事無く代替えのプロキシを使わせるかでしょう。

単純な方法として浮かぶのは、DNSの指定によってプロキシを代替えのマシンのIPアドレスに切り替える方法でしょう。
しかし、この方法は多分うまく行きません。 一般的なクライアントではDNSのが一度行われると、その際に検索したアドレスを数十分、場合によっては数時間クライアントPC内に保持してしまいます。
このため、DNSでIPアドレスを切り替えても相変わらず昔のプロキシを探しにいってしまうことでしょう。

勿論、各クライアントでDNSキャッシュをリフレッシュを手動で行うことで、正常なプロキシを見にいくようにさせる事は可能ですが現実的では無いと思われます。
なお、DNSラウンドロビンによって"proxy"という名前に複数のIPアドレスを定義したとしても、同じ理由によって問題が発生する事でしょう。

■ロードバランサによる冗長化:

Proxyを複数構成にするとともに、ロードバランサを組み合わせることでクライアントからは単一のProxyして見せかけ、かつ、ロードバランサを冗長化することで、比較的低コストで高性能なProxy環境を構築できます。
クライアントから見た場合、見かけ上はロードバランサがProxyとして見えますが、ロードバランサーの上位に複数のProxyを用意することで、Proxyの障害に備えるとともにロードバランサによるProxyサーに対するアクセスの分配により高速なアクセスが可能になります。

ロードバランサとしては F5 の製品が有名ですが、フリーソフトを使ったロードバランサでも十分に実用に耐えます。 別章では、ロードバランサとして「HAProxy」、冗長化に「heartbeat」を使った構成について述べていきます。
この構成をとった場合、ロードバランサの障害はハートビートによる機器の冗長化で対処するとともに、Proxyの障害には複数のProxyサーバを用意することで対応します。 また、ロードバランサ上位のProxyを増やすことで容易にProxyの性能向上を図ることが可能です。

■クラスタサーバによる冗長化に関して:

予算が潤沢な企業であれば、複数のプロキシサーバをクラスタとして設計して、代替えのプロキシサーバをホットスタンドバイさせて、主系のサーバが停止した場合に、同じIPアドレスや環境で代替えのプロキシを自動的に切り替える方法もあります。 

(クラスタによる切り替え概念図)

ただし、クラスタは常にシステムが2倍以上のコスト高になる可能性があり、コスト面からは最適ではないかも知れません。 特に大量のクライアントがある環境においては、地域で集約するProxyが大量になり、コストが肥大することになると思われます。

■単純なサーバ分散:

Proxyの障害は、組織内のWebサーバサービス利用全体に影響を与える可能性があるため、その構築については連続稼働時間性能を高めた構成をとることが望ましいでしょう。
そのために一番簡単な方法は、複数のProxyサーバを用意しておきあるルール単位(例えば、地域やサブネット)で利用できるProxyサーバを分ける方法が考えられます。

この方法ではProxyサーバの障害発生時に全クライアントがアクセス不能にならない為、比較的低コストでProxyサーバの障害時の影響を軽減することが可能です。 また下記で説明するスクリプトファイルの併用によって、障害におけるクライアントへの影響をほぼなくす事が可能です。
反面、地域の数が増えたりスクリプトの変更などのといった運用コストは増大する可能性があり、特にユーザにどのProxyを利用させるかといった管理は常に必要になります。
また、Proxyの性能に問題があってもその性能向上を図ることはハードウェアの性能を上げる必要があり容易では無いでしょう。

■スクリプトによる冗長化に関して:

IEやNetscapeには、プロキシの設定をスクリプト(Javascript)で定義する方法が用意されています。 この機能を使うことで、プロシキの設定を環境に合わせて柔軟に切り替える事が可能になります。 また、スクリプトを使った場合、常に使用するプロキシが使えない場合に、セカンダリのプロキシを複数指定できるので、これを使った経路の冗長化が可能になります。
スクリプトとして、以下のようなスクリプト(proxy.pac)を紹介します。

このスクリプトでは、例えば東京のセグメントにあるクライアントは、プロキシとして"proxy-tk"を通常は利用し、"proxy-tk"が反応しないときには自動的に"proxy-osaka"を使うようになっています。
// (proxy.pac)
// このJavascriptでは、
// 社内全体のネット : 172.16.0.0/12 (172.16.0.0 - 172.31.255.255)
// Tokyo-LAN(東京) : 172.16.0.0/16
// Osaka-LAN(大阪) : 172.17.0.0/16
// Fukuoka-LAN(福岡) : 172.18.0.0/16
// として、各拠点にプロキシを配置し、それぞれのセグメントに接続された時に最寄りのプロキシを
// 自動的に選択する処理を行う。 // もし、最寄りのプロキシが反応しない場合にはサブのプロキシを使うようにする。
// また、社内のWebサーバへのアクセスにはプロキシを経由しないようにする。
//
function FindProxyForURL(url, host) {
MyDomain = ".hogehoge.jp";
MyIP = myIpAddress();
NetworkID = 0 ; // Default = 0(Tokyo), 1(Osaka), 2(Fukuoka)
ProxyTokyo="PROXY proxy-tk.hogehoge.jp:8080; PROXY proxy-osaka.thogehoge.jp.co.jp:8080" ;
ProxyOsaka="PROXY proxy-osaka.hogehoge.jp:8080; PROXY proxy-tk.hogehoge.jp:8080" ;
ProxyFukuoka="PROXY proxy-fukuoka.hogehoge.jp:8080; PROXY proxy-tk.hogehoge.jp:8080" ;

// まず、社内のWebサーバのアクセスかどうかを確認。
if ( isInNet(host, "172.16.0.0" , "255.240.0.0" ) || dnsDomainIs(host, MyDomain) || isPlainHostName(host) ) {
return "DIRECT" ;
}

if (isInNet(MyIP, "172.17.0.0", "255.255.0.0")) NetworkID = 1 ;
if (isInNet(MyIP, "172.18.0.0", "255.255.0.0")) NetworkID = 2 ;

switch ( NetworkID ) {
case 1: // 大阪LAN
return ProxyOsaka ;
break;
case 2: // 福岡LAN
return ProxyFukuoka ;
break;
default: // 東京LAN
return ProxyTokyo ;
break;
}
}
このスクリプトを作成したなら、これをクライアント側に反映させるには2つの方法が考えられます。 

1つは、このスクリプトをイントラのWebサーバに登録しておき、そのWebサーバをブラウザで指定する方法です。

この方法をとった場合、サーバ側のスクリプトを変更すればクライアントすべてにその結果を反映させる集中管理が可能です。反面、万一イントラのWebサーバが障害を起こした場合には、プロキシの情報をを利用できなくなってしまうので、すべての端末でWebアクセスが不能になります。

もう1つは、このスクリプトを自分のPCに保存しておき、呼び出す方法です。
以下の例では、C:\My Document\proxy.pacを呼び出しています。

※ NetscapeやMozillaなどでは、ファイルの指定の際のドライブの指定は"c:"ではなく"c|"とする。(例:file://c|/My Document/proxy.pac)

この方法であれば、設定は各クライアントに必要となりますが確実に経路を冗長化させることができます。ただし、スクリプトの変更が必要な場合、都度ユーザによる作業が必要となる可能性があり、運用コストは増大する可能性もあります。
Squid Home / FAQトップ

参考: