Aqutras Members' Blog

株式会社アキュトラスのメンバーが、技術情報などを楽しく書いています。

apacheでmod_proxyとmod_cacheを使ってリバースプロキシでキャッシュを行う

こんにちは,mbuchiです.

先日私的な用件で,リバースプロキシに動的コンテンツも含めてキャッシュさせる方法を探しました.

特にキャッシュ周りの情報が少なくて苦戦したので,ここにまとめておきます.

構築するもの

動的コンテンツもキャッシュするリバースプロキシ

環境

  • Ubuntu 14.04
  • Apache 2.4.7 (apt-getで入れたもの)

使うもの

  • mod_proxy
  • mod_cache

必要な手順

1. mod_proxyの設定

hico-horiuchi.hateblo.jp

こちらのサイトが分かりやすかったです.

ここでは省略します.

2. mod_cacheの設定

/etc/apache2/mods-available/cache_disk.confに追記

# アンコメント
CacheEnable disk /  # 15行目

# 追記
CacheIgnoreCacheControl On # キャッシュされているコンテンツを返さないようにクライアントから リクエストされても無視する
CacheStorePrivate On  # private と指定されているレスポンスのキャッシュを試みる。
CacheIgnoreNoLastMod On # 応答にLast Modified が無くてもキャッシュする
CacheStoreNoStore On # no-store と指定されているレスポンスのキャッシュを試みる。
CacheDefaultExpire 3600 # キャッシュの有効期限(秒)
CacheLock on # Thundering Herd 問題対策

Thundering Herd問題については以下のサイトで知りました.

Kazuho@Cybozu Labs: キャッシュシステムの Thundering Herd 問題

例えば同一URLへのアクセスがほぼ同時に2件来た場合,キャッシュは無い状態なので,2件ともオリジナルのサーバへアクセスするという問題への対応をしてくれるオプションという理解です.

注意点

CacheStoreNoStore について

RFC 2616 に記載されているように no-store ディレクティブは、 "不注意による機密情報の漏洩や残留 (バックアップテープ等) を防ぐ" 目的で使われますが、このオプションを有効にすると、 機密情報を保持することになってしまいます。 ですので、ここで警告しておきます。mod_cache - Apache HTTP サーバより

3. テストしてみる

1. クライアントから2回アクセスする

$ curl http://proxy_server/index.cgi; sleep 1; curl http://proxy_server/index.cgi

2. リバースプロキシから飛ばされるオリジナルのサーバのログを確認

/var/log/apache2/access.logを確認します.

192.168.0.3,-,-,[01/Jun/2016:16:24:01 +0900],"GET /index.cgi HTTP/1.1",200,13779,0,17406

プロキシへのアクセスは2回行われていますが,オリジナルのサーバへは1回しかアクセスが来ていません. キャッシュできていることが確認できました.

4. さらにテストしてみる

並列でリクエスト送ってみる

先程は1つずつでしたが,今度はリクエストを並列して送ってみます. GNU parallelを使います. GNU parallel自体の説明は,以下のサイトがわかりやすかったです.

bicycle1885.hatenablog.com

クライアント側
$ parallel curl :::  http://proxy_server/index.cgi http://proxy_server/index.cgi

実行される内容としては,curl http://proxy_server/index.cgiが2つ並列に走ります.

オリジナルのサーバのログ
192.168.0.3,-,-,[01/Jun/2016:17:07:30 +0900],"GET /index.cgi HTTP/1.1",200,13779,0,17646

1回だけアクセスされています.

CacheLockをoffにして並列でアクセスする

2.で設定したキャッシュサーバのcache_disk.confCacheLock OnOffにして実験してみます. ちなみにデフォルト値はOffなので,この行を削除でも可です.

クライアント側
$ parallel curl :::  http://proxy_server/index.cgi http://proxy_server/index.cgi
オリジナルのサーバのログ
192.168.0.3,-,-,[01/Jun/2016:16:57:17 +0900],"GET /index.cgi HTTP/1.1",200,13779,0,16586
192.168.0.3,-,-,[01/Jun/2016:16:57:17 +0900],"GET /index.cgi HTTP/1.1",200,13779,0,12987

先ほどとは違い,アクセスが2回とも来ています.

まとめ

動的コンテンツもキャッシュするリバースプロキシの構築方法でした.

天気予報,商品の在庫数を表示するようなECサイト,掲示板(数秒ごとにキャッシュ更新すれば可?)など,極端にリアルタイム性を求められないサイトでお使いいただけるのではないでしょうか.

Thundering Herd問題は聞いたことがなかったので,今回いろいろと調べたなかで,特に良い勉強になりました.

上で貼ったもの以外に参考にさせていただいたページ

Apache2.2の mod_proxyと mod_cacheであらゆるものをキャッシュする - ブログ - ワルブリックス株式会社

mod_cache - Apache HTTP Server Version 2.4