Apacheロードバランサで負荷分散。冗長化構成を開発環境でも。~負荷分散と冗長化の基礎を添えて~

公開
注意最終更新から 8 年以上経過しています。最新の情報もあわせてご確認ください。

ロードバランサは AWS などクラウドサービス出現のおかげでかなり気軽に使えるようになりました。とはいえ、アプリケーションの開発時に冗長化構成下の動作確認を気軽に行いたいと思う場合もあったりします。

今回は、負荷分散や冗長化の基本をさらいつつ、Apache を使って冗長化構成時のロードバランシングを行います。

開発環境

今回の開発環境は以下の通りです。

  • Linux CentOS 7
  • Apache 2.4

仮想環境で WEB サーバを3機用意しています。

  • 192.168.80.10 ロードバランシング用
  • 192.168.80.11 WEB サーバ 1
  • 192.168.80.12 WEB サーバ 2

負荷分散とロードバランサ

処理やトラフィックなど WEB サーバ1台では処理しきれない場合に、サーバを複数台用意して負荷分散装置「ロードバランサ」を用いて各サーバへ振り分けを行う事で、サーバ1台にかかる負荷を分散させる事が出来ます。

負荷分散方式

ロードバランサで用いられる負荷分散方式は以下の通りです。

  • ラウンドロビン方式
    • 順番にサーバを割り振っていく
  • 重み付けラウンドロビン方式
    • 定義した割合でサーバを割り振っていく
  • 最速応答時間方式
    • 応答が最も早いサーバへ割り振る
  • 最小コネクション方式
    • 接続コネクション数が最も少ないサーバへ割り振る
  • 最小トラフィック方式
    • 一定時間で転送されたデータ量が最も少ないサーバへ割り振る
  • CPU負荷分散方式
    • CPU の負荷が最も低いサーバへ割り振る
  • セッション維持方式
    • IP や Cookie などを基にサーバへ割り振る

ロードバランサ導入時の注意点

  • システム構成が複雑化する
  • ログがサーバ台数分散らばる

Apache の Proxy と負荷分散

Apache での負荷分散は Proxy 機能を応用する事で実現しています。

フォワード Proxy

  • キャッシュされたデータを WEB サーバの代わりに返す
  • 外部ネットワークから断絶されているイントラネット内のクライアントが外部のサイトを参照したりできる

リバース Proxy

  • ロードバランシングはこっち
  • インターネット側からのリクエストを中継し、WEB サーバへ割り振る
  • コンテンツの分散や WEB サーバ構成を外部から隠蔽する時などで使われる
  • リバース Proxy 機能に負荷分散や冗長性を装備する事でロードバランサとして使用できる

Apache で Proxy 機能を使うには、拡張モジュール「mod_proxy 」が必要になります。

  • mod_proxy
    • Proxy 機能を可能にする
  • mod_proxy_balancer
    • ロードバランス機能を可能にする
  • mod_proxy_ftp
    • FTP プロトコルを Proxy できるようにする
  • mod_proxy_http
    • HTTP プロトコルを Proxy できるようにする
  • mod_proxy_ajp
    • AJP プロトコルを Proxy できるようにする
  • mod_proxy_connect
    • トンネリングのおための CONNECT メソッドを Proxy できるようにする

Apache で負荷分散

負荷分散機能は拡張モジュール「mod_proxy_balancer 」で実現します。 HTTP/サーブレットコンテナ/AJP13/FTP のバランシングが可能です。 Apache2.2 以降での負荷分散、冗長化機能は以下の通りです。

負荷分散

  • リクエスト回数を基に割り振る
  • トラフィック量を基に割り振る
  • セッション変数を利用する場合、セッション情報を保持しているサーバに接続して割り振る
  • 設定を動的に変更できるマネージャを利用できる
  • マネージャを利用する事で各バックエンドサーバの状態を確認できる
  • マネージャは WEB ブラウザから利用できる

冗長化

  • httpd の再起動不要でバックエンドサーバをオンライン/オフラインできる
  • バックエンドサーバのダウンを自動で検知し分散対象から外す
  • バックエンドサーバが障害から復帰した場合は自動で分散対象にする
  • バックエンドサーバのオンライン/オフラインを変更するマネージャが使える
  • マネージャを利用する事で各バックエンドサーバの状態を確認できる
  • マネージャは WEB ブラウザから利用できる

冗長化とセッション

PHP ではアプリケーションでログインでのユーザ認証などでセッションを使う事があります。

IP や固有 ID を埋め込んだ Cookie 情報を基に、サーバ側でクライアントを識別しクライアントごとの変数をサーバ側で保持するようにすることで、WEB ブラウザが画面遷移してもログインなどの情報を引き継げます。その時にサーバ側で保存されるのが「セッション変数」です。

しかし冗長化構成下では、リクエストが振り分けられるので、認証を行ったサーバではないところへ割り振られた場合、認証情報を引き継ぐ事ができず WEB ブラウザと HTTP サーバとでは永続的な処理を行う事ができません。

ロードバランサを導入して冗長化構成にする場合、サーバ間でセッション情報を共有する必要があります。

Apache Tomcat のようなアプリケーションサーバではメモリ・ディスク・ RDBMS にセッション情報を保存する「セッションレプリケーション」が提供されていますが、これに頼らなくても Apache2.2 以降ではクライアントからのリクエストを、セッション変数が保存されているサーバに固定して割り振ることができます。これを「スティッキーセッション方式」と呼び、セッション変数を永続化して利用できます。

負荷分散に必要な拡張モジュール

Proxy関連モジュールが有効になっているかを確認します

# httpd -M | grep proxy
 proxy_module (shared)
 proxy_ajp_module (shared)
 proxy_balancer_module (shared)
 proxy_connect_module (shared)
 proxy_express_module (shared)
 proxy_fcgi_module (shared)
 proxy_fdpass_module (shared)
 proxy_ftp_module (shared)
 proxy_http_module (shared)
 proxy_scgi_module (shared)
 proxy_wstunnel_module (shared)

最低でも以下がインストールされている必要があります。

  • proxy_module(mod_proxy)
  • proxy_balancer_module(mod_proxy_balancer)

URL での割り振り

以下のルールでバックエンドサーバへの割り振りを設定します。

  • http://192.168.80.10/serv1 へのアクセスで 192.168.80.11 へ割り振り
  • http://192.168.80.10/serv2 へのアクセスで 192.168.80.12 へ割り振り

conf ファイルを設定します。

<IfModule mod_proxy.c>
ProxyRequests off

ProxyPass /serv1 http://192.168.80.11
ProxyPassReverse /serv1 http://192.168.80.11

ProxyPass /serv2 http://192.168.80.12
ProxyPassReverse /serv1 http://192.168.80.12
</IfModule>

ProxyRequests ディレクティブを off にする事でフォワード Proxy 機能を無効化し、リバース Proxy を有効化しています。

ProxyPass/ProxyPassReverse ディレクティブで URL のマッピングを行っています。リモートサーバをローカルサーバの名前空間にマップしています。

httpd を再起動し、ブラウザからアクセスしてみます。

URL での振り分け結果

URL によってサーバが割り振られている事が確認できました。

リクエスト回数やトラフィック量での割り振り

vim /etc/httpd/conf/httpd.conf
<IfModule mod_proxy.c>
ProxyRequests off

ProxyPass / balancer://samplecluster lbmethod=byrequests timeout=1 maxattempts=2

<Proxy balancer://samplecluster>
        BalancerMember http://192.168.80.11 loadfactor=3
        BalancerMember http://192.168.80.12 loadfactor=2
</Proxy>
</IfModule>

ProxyPass には以下の順で設定します。

  • バランシング対象のパス
  • balancer://任意の名前
  • lbmethod=負荷分散アルゴリズム
  • timeout=接続タイムアウト(秒)
  • maxattempts=接続試行回数

負荷分散アルゴリズムは以下の2つで設定します。

  • リクエスト回数「byrequests」
  • トラフィック量「bytraffic」

また、loadfactor を設定する事で、振り分けの比率を設定することが出来ます。(設定値は 1~ 100)

maxattempts に関して、バックエンドサーバがダウンした場合は自動で振り分け対象から外れます(フェイルオーバー)が、それを判断する為の接続試行回数になります。

ちなみに、振り分け対象から外れた時には、ロードバランサ側の error_log に以下のようにロギングされます。

[Sun Jul 01 07:28:09.431996 2018] [proxy:error] [pid 4644] (111)Connection refused: AH00957: HTTP: attempt to connect to 192.168.80.12:80 (192.168.80.12) failed
[Sun Jul 01 07:28:09.432040 2018] [proxy:error] [pid 4644] AH00959: ap_proxy_connect_backend disabling worker for (192.168.80.12) for 60s

尚、これらの項目は全てが必ず設定しなくてはいけないものではなく、以下に関しては未設定ならばデフォルト値が設定されます。

  • timeout=1
  • maxattempts=1
  • loadfactor=1

httpd 再起動の後、ブラウザからアクセスしてみます。

トラフィックでの振り分け結果

振り分けが行われている事が確認できました。

スティッキーセッションの設定

スティッキーセッションを設定しセッション情報を維持するには以下のように設定します。

vim /etc/httpd/conf/httpd.conf
ProxyPass /sample balancer://samplecluster lbmethod=byrequests timeout=1 maxattempts=1 nofailover=On stickysession=PHPSESSIONID 

PHP の場合、stickysession=PHPSESSIONID を追加します。

尚、バックエンドサーバ側でセッションレプリケーション機能を持たない場合は nofailover=On を追加します。

Load Balancet Manager

Apache には負荷分散や冗長化機能のためのマネージャがあります。マネージャは WEB ブラウザから利用でき、設定変更・バックエンドサーバの状態確認・バックエンドサーバの切り離しなどが行えます。

マネージャで変更した内容はすぐに反映され、サーバを再起動する必要もありませんが、変更した内容は conf ファイルに反映されないので、再起動を行うと元に戻る点に注意が必要です。

マネージャの利用には拡張モジュール「mod_status 」が必要です。

# httpd -M | grep status
 status_module (shared)
vim /etc/httpd/conf/httpd.conf
<Location /balancer-manager>
SetHandler balancer-manager

PostsListOrder Deny,Allow
Deny from all
Allow from 127.0.0.1 192.168.80.
</Location>

httpd の再起動後、ブラウザから確認します。

LoadBalancetManager

このように、ブラウザから設定を変更することができます。

まとめ

以上で作業は完了です。 PHP では認証機能などセッション管理を必要とするアプリケーションの開発も多く、確認環境まで上げないと冗長化構成下でのテストが行えないなど微妙にやりにくい部分がありますが、こうして Apache を使って一時的にでもローカル環境で冗長化構成を構築してしまえば気軽にテストが行えるので、是非試してみてください。

Ritolabo