mod_proxy_balancer + mod_disk_cache on Apache 2.2.3

Apache2.2.3の環境下で mod_proxy_balancer と mod_disk_cache を使い、キャッシュサーバを構築したのでメモしておきます。

イメージする構成としては、まずフロントエンドにApacheのReverse Proxy Serverがあり、そしてその裏側に実際にアクセスする複数台のWeb Server(以下の例では5台)があります。

クライアントからのアクセスを受けると、リバースプロキシは、負荷分散アルゴリズムにしたがって、実際のウェブサーバへリクエストを投げることになります。その際、画像コンテンツのみをキャッシュし、次回以降のアクセスではキャッシュファイルのみを返すようにします。

ということで早速設定してみます。

mod_proxy_balancerモジュールを有効にするためには、mod_proxyおよびmod_proxy_httpモジュールが有効になっている必要があります。またリバースプロキシ側でmod_rewriteを使いたい場面があるので、これも有効にしておきます。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

LoadModule status_module modules/mod_status.so

LoadModule rewrite_module modules/mod_rewrite.so

ProxyRequests Off

ProxyPassReverse / http://192.168.1.10/
ProxyPassReverse / http://192.168.1.11/
ProxyPassReverse / http://192.168.1.12/
ProxyPassReverse / http://192.168.1.13/
ProxyPassReverse / http://192.168.1.14/

<Proxy balancer://web-cluster>
    BalancerMember http://192.168.1.10 loadfactor=1
    BalancerMember http://192.168.1.11 loadfactor=1
    BalancerMember http://192.168.1.12 loadfactor=1
    BalancerMember http://192.168.1.13 loadfactor=1
    BalancerMember http://192.168.1.14 loadfactor=1
</Proxy>

RewriteEngine on

RewriteRule ^/balancer_manager$ /balancer_manager [L]

LoadModule cache_module modules/mod_cache.so
<IfModule mod_cache.c>
     LoadModule disk_cache_module modules/mod_disk_cache.so
     <IfModule mod_disk_cache.c>
          # mkdir -p /www/example.com/proxy
          # chown nobody:nobody /www/example.com/proxy
          CacheRoot /www/example.com/proxy
#          CacheEnable disk /
          CacheEnable disk /images
          CacheEnable disk /icons
          CacheDirLevels 5
          CacheDirLength 3
          # unit is second
          CacheDefaultExpire 3600
     </IfModule>
</IfModule>

# Balancer: Remote Web Servers
RewriteRule ^/(.*)$ balancer://web-cluster/$1 [P]

<Location /balancer_manager>
    SetHandler balancer-manager
    Order Deny,Allow
    Deny from all
    Allow from 192.168.1.20
</Location>

ディスクキャッシュ機能は実用レベルに達しているので、今回はディスクにキャッシュ機能を有効にします。

まず事前にディレクトリを作成しておく必要があります。

# mkdir -p /www/example.com/proxy
# chown nobody:nobody /www/example.com/proxy

設定すべきディレクティブは、ドキュメントを参考にして下さい。

以下の例では、images/ と icons/ 以下のコンテンツをディスク上にキャッシュすることになります。またキャッシュの有効期限は1日に設定してあります。

LoadModule cache_module modules/mod_cache.so
<IfModule mod_cache.c>
     LoadModule disk_cache_module modules/mod_disk_cache.so
     <IfModule mod_disk_cache.c>
          CacheRoot /www/example.com/proxy
#          CacheEnable disk /
          CacheEnable disk /images
          CacheEnable disk /icons
          CacheDirLevels 5
          CacheDirLength 3
          # unit is second
          CacheDefaultExpire 3600
     </IfModule>
</IfModule>

コンテンツがキャッシュ可能かどうかの判定は以下の条件に従います。


・リクエストされたURLにおいてキャッシングが有効であること
・レスポンスはHTTPステータスが200,203,300,301および410であること
・GETリクエストであること
・リクエストにAuthorization:ヘッダがある場合はキャッシュしない
・レスポンスにAuthorization:ヘッダがある場合は、同時にCache-Control:ヘッダで「s-maxage」「must-revalidate」もしくは「public」オプションが指定されていること
・URLにクエリ文字列がある場合は、そのレスポンスにExpires:ヘッダがない限りキャッシュしない
・レスポンスのHTTPステータスが200(OK)の場合、CacheIgnoreNoLastModディレクティブが指定されていない限り、同時にEtag:、Last-Modified:もしくはExpires:ヘッダの少なくともひとつが存在しなければならない
・もしレスポンスの「Cache-Control」ヘッダに「private」オプションが指定されている場合、CacheStorePrivateディレクティブが指定されていない限りキャッシュしない
・同様に、レスポンスの「Cache-Control」ヘッダに「no-store」オプションが指定されている場合、CacheStoreNoStoreディレクティブが指定されていない限りキャッシュしない
・レスポンスの「Vary:」ヘッダにマッチオール「*」が指定されている場合はキャッシュしない

上記のディスクキャッシュ機能の設定を追記したのが、以下の設定ファイルになります。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

LoadModule status_module modules/mod_status.so

LoadModule rewrite_module modules/mod_rewrite.so

ProxyRequests Off

ProxyPassReverse / http://192.168.1.10/
ProxyPassReverse / http://192.168.1.11/
ProxyPassReverse / http://192.168.1.12/
ProxyPassReverse / http://192.168.1.13/
ProxyPassReverse / http://192.168.1.14/

<Proxy balancer://web-cluster>
    BalancerMember http://192.168.1.10 loadfactor=1
    BalancerMember http://192.168.1.11 loadfactor=1
    BalancerMember http://192.168.1.12 loadfactor=1
    BalancerMember http://192.168.1.13 loadfactor=1
    BalancerMember http://192.168.1.14 loadfactor=1
</Proxy>

RewriteEngine on

RewriteRule ^/balancer_manager$ /balancer_manager [L]

LoadModule cache_module modules/mod_cache.so
<IfModule mod_cache.c>
     LoadModule disk_cache_module modules/mod_disk_cache.so
     <IfModule mod_disk_cache.c>
          # mkdir -p /www/example.com/proxy
          # chown nobody:nobody /www/example.com/proxy
          CacheRoot /www/example.com/proxy
#          CacheEnable disk /
          CacheEnable disk /images
          CacheEnable disk /icons
          CacheDirLevels 5
          CacheDirLength 3
          # unit is second
          CacheDefaultExpire 3600
     </IfModule>
</IfModule>

# Balancer: Remote Web Servers
RewriteRule ^/(.*)$ balancer://web-cluster/$1 [P]

<Location /balancer_manager>
    SetHandler balancer-manager
    Order Deny,Allow
    Deny from all
    Allow from 192.168.1.20
</Location>

注意すべき点がいくつかあります。

  • 負荷分散を行なう場合、各サーバのコンテンツに違いがあるとキャッシュされず都度サーバへのアクセスが発生する
  • 有効期限が切れる前にコンテンツの中身を変更した場合、キャッシュをレスポンスとして返す
  • 有効期限が切れる前にコンテンツを削除した場合、キャッシュをレスポンスとして返す