Apacheの「mod_cache」を使って、手軽にコンテンツキャッシュ機能を実装する。

サーバ負荷の軽減の為に動的なコンテンツをキャッシュする場合、定番のsquidVarnishをはじめ、いろいろと方法がありますが、手軽な方法として、Apacheのmod_cacheモジュールを使うという選択肢もあります。

例えば、サーバリソースも限られていたりするさくらのVPS等とかに適した感じです。ということで、さくらのVPSにmod_cacheの設定を行いたいと思います。

mod_cacheの設定と動作の確認

  1. まずは、必要なモジュールをロードします。(デフォルトで有効かも。)mod_cacheは、ストレージにディスクかメモリかを選択できます。今回は、あまりメモリに余裕がないので、ディスクを使うことにします。

    LoadModule cache_module modules/mod_cache.so
    LoadModule disk_cache_module modules/mod_disk_cache.so

    mod_cache はローカルのコンテンツやプロキシされた コンテンツをキャッシュするために使われる RFC 2616 準拠の HTTP コンテンツキャッシュを実装しています。mod_cache の動作にはストレージを管理するモジュールが必要です。標準 Apache 配布には二つストレージ管理モジュールが含まれています:

    mod_cache – Apache HTTP サーバ

  2. キャッシュファイルを保存するディレクトリを設定します。

    # mkdir /var/tmp/cache
    # chmod 777 /var/tmp/cache
  3. Apacheの設定を行います。今回は、ホストごとに設定したかったりするので、バーチャルホスト内に設定を行います。

    vi /etc/httpd/conf.d/vhost.conf
    <IfModule mod_cache.c>
        <IfModule mod_disk_cache.c>
            CacheRoot /var/tmp/cache
            CacheEnable disk /
            CacheDisable /img
            CacheIgnoreCacheControl On
            CacheIgnoreNoLastMod On
            CacheDefaultExpire 86400
            CacheMaxExpire 172800
        </IfModule>
    </IfModule>
    • CacheRootでキャッシュファイルの保存先のパスを指定します。

      CacheRoot ディレクティブはキャッシュファイルを 保管するためのディスク上のディレクトリを指定します。

      mod_disk_cache – Apache HTTP サーバ

    • CacheEnableでキャッシュストレージやキャッシュするコンンテンツを指定します。

      CacheEnable ディレクティブで mod_cache モジュールが url-string 以下の URL をキャッシュするようにします。 キャッシュストレージ管理方式は cache_type 引数で指定します。

      mod_cache – Apache HTTP サーバ

    • 静的な画像コンテンツ等については、既にブラウザキャッシュの設定がしてあったりするので、それで良しとして、CacheDisableを設定して、キャシュするコンテンツから除外します。

      CacheDisable ディレクティブで mod_cache モジュールが url-string 以下の URL をキャッシュしないようにします。

      mod_cache – Apache HTTP サーバ

    • CacheIgnoreCacheControlをOnにして、強制でキャッシュコンテンツを返すようにします。

      一方、ブラウザのリロードボタンを押した場合など、ブラウザからのリクエストがキャッシュ制御情報を示すヘッダ(例えば、Cache- Control: no-cache、Cache-Control: max-age=0、Pragma: no-cacheなど)を含む場合には、下図のように、mod_cacheはキャッシュのチェックを行わず、バックエンドシステムにアクセスし、レンダリング結果を得、それをキャッシュした上でブラウザに返します。
      ただし、mod_cacheにはCacheIgnoreCacheControlというディレクティブが用意されており、値をOnにした場合にはリクエストに含まれるCache-Controlヘッダを無視して、キャッシュにヒットすればキャッシュ内の情報を返します。

      Ogawa::Buzz: もう少しだけmod_cacheを深追いしてみる

      Cache-Control: no-cache ヘッダや Pragma: no-store ヘッダのあるリクエストに 対しては、通常キャッシュを使いません。CacheIgnoreCacheControl ディレクティブを使うと、この動作を上書きできます。 CacheIgnoreCacheControl On とすると、 リクエストに no-cache という値があっても、キャッシュを使ってドキュメントを 返すようになります。

      mod_cache – Apache HTTP サーバ

    • CacheIgnoreNoLastModをOnにして、Last-Modifiedの無いコンテンツもキャッシュされるようにします。

      通常、Last-Modified による最終修正時刻の無いドキュメントはキャッシュ されません。(例えば mod_include による処理のときなどに) Last-Modified 時刻が消去されたり、そもそも最初から提供されていない 状況があります。CacheIgnoreNoLastMod ディレクティブを使うと、Last-Modified 日時が指定されていない ドキュメントでもキャッシュするように指定できます。

      mod_cache – Apache HTTP サーバ

    • CacheIgnoreNoLastMod等で期限の生成に使われる、CacheDefaultExpireを設定します。

      CacheDefaultExpire ディレクティブは、ドキュメントに 有効期限 (expiry) や最終修正時刻 (last-modified) が指定されていない場合の デフォルトの時間を指定します。

      mod_cache – Apache HTTP サーバ

    • キャッシュされる期間の最大値を設定します。なお、この値は、CacheLastModifiedFactorの値より優先され、CacheDefaultExpireの値より優先されません。

      CacheMaxExpire ディレクティブは、 キャッシュする HTTP ドキュメントを、元のサーバに問い合わせないまま最大何秒 保持してもよいかを指定します。

      mod_cache – Apache HTTP サーバ

  4. 以上で、mod_cacheの設定は完了です。動作を確認してみます。CacheDefaultExpireを10に設定して、Apacheを再起動して、設定を反映させます。

    /etc/init.d/httpd restart

    テストファイルを作成してキャッシュの挙動を確認してみます。

    vi /var/www/html/test.php
    <?php
    echo date("r");
    ?>
    

    ブラウザで連続してリロードしても10秒ごとにしか更新されません。ということで、コンテンツがしっかりキャッシュされているようです。

    が!しかし、HTTPステータスコードを確認すると、毎回、

    HTTP/1.1 200 OK

    となっています。

    ブラウザキャッシュが有効になるように、ファイルにEtagの設定を追記します。

    vi /var/www/html/test.php
    <?php
    header("Etag: test");
    echo date("r");
    ?>
    

    If the response has a status of 200 (OK), the response must also include at least one of the “Etag”, “Last-Modified” or the “Expires” headers, or the max-age or s-maxage directive of the “Cache-Control:” header, unless the CacheIgnoreNoLastMod directive has been used to require otherwise.

    Caching Guide – Apache HTTP Server

    再度、ブラウザで連続してリロードすると10秒ごとにしか更新されず、かつ、HTTPステータスコードは、

    HTTP/1.1 304 Not Modified

    となっています。

    これで、OKかと思いきや、このままでは、URLに?test=testのようなクエリ文字列があるとキャシュされなくなってしまいます。さらにExpiresの設定を追加します。

    vi /var/www/html/test.php
    <?php
    header("Etag: test");
    header("Expires: ".gmdate("D, d M Y H:i:s",time() + 5)." GMT");
    echo date("r");
    ?>
    

    If the URL included a query string (e.g. from a HTML form GET method) it will not be cached unless the response specifies an explicit expiration by including an “Expires:” header or the max-age or s-maxage directive of the “Cache-Control:” header, as per RFC2616 sections 13.9 and 13.2.1.

    Caching Guide – Apache HTTP Server

    ブラウザで連続してリロードすると5秒ごとにしか更新されず、かつ、HTTPステータスコードは、

    HTTP/1.1 304 Not Modified

    となっており、クエリ文字列があっても挙動は変わりません。

まとめ

以上で、設定と動作確認の完了です。あとは、今回の動作等をを踏まえたうえで、設定を行って、実際のコンテンツをキャッシュして、違いを計測してみたりしたいと思います。

カテゴリー: サーバ・インフラのこと   タグ: ,   この投稿のパーマリンク

トラックバック

Apacheの「mod_cache」を使って、手軽にコンテンツキャッシュ機能を実装する。 への1件のコメント

  1. ピンバック: YSlow対応その4(Apache2.2.4のmod_disk_cachを利用してストレージ 管理機構を実装) | 自宅サーバ練習用ブログ

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>