SOFTELメモ

</> 技術者募集

【Apache】mod_cacheで動的コンテンツのキャッシュをさせる

問題

Apacheにもキャッシュ機能があるらしいけど、どんな風に使うの?

動的に生成されるページや画像のキャッシュに使える?

apache-icon

答え

使える。

mod_cacheを使うと、プログラムにはほぼ手を加えないで、動的コンテンツのキャッシュをApacheにお願いできる。

キャッシュ先は標準で、メモリ(mod_mem_cache)とファイル(mod_disk_cache)がある。動作はそれぞれ違いがある(メモリならプロセス単位でキャッシュされるらしいとか、ディスクを使うと当然I/Oが発生するとか)。細かいところはマニュアルなどで研究されたし。

mod_disk_cacheの場合の設定例

mod_cache と mod_disk_cache をロードするように設定して、mod_disk_cacheの設定をする。

#特定の状況でキャッシュを有効にしたかったら、全体では有効にしないでおく

<VirtualHost *:80>
    ServerName example.com

    #キャッシュを有効にしたいVirtualHostやディレクトリの設定の中で
    #キャッシュの保存先、キャッシュしてもらいたいパスや動作を設定
    CacheRoot /var/cache/httpd/mod_disk_cache
    CacheDirLevels 5
    CacheDirLength 2
    CacheIgnoreCacheControl On # クライアント側でF5されてもCtrl+F5などされてもキャッシュを使う
    #CacheIgnoreURLSessionIdentifiers jsessionid PHPSESSID # 状況に応じて
    #CacheIgnoreHeaders Set-Cookie # 状況に応じて
    CacheEnable disk /image.php # http://~~/image.php?~などをキャッシュする

</VirtualHost>

CacheRoot(上の設定では /var/cache/httpd/mod_disk_cache)は、場所はどこでもよいが、初期状態で存在しなかったら作ってあげて、httpdの実行ユーザーが書き込みできるようにしておく。

mod_disk_cacheだと、CacheRoot以下にキャッシュファイルが生成される様子などが見て分かる。

キャッシュの操作

htcachecleanというツールが用意されていて、mod_disk_cacheのキャッシュを削除することができる。

やれることは割と単純で、容量を指定して削除、URLを指定して削除、常駐させて定期的に削除など。

例)キャッシュが10MB以内になるように削除

# htcacheclean -r -p /var/cache/httpd/mod_disk_cache -l 10M

心配なときは、-D -v でどうなるか確かめてから。

# htcacheclean -D -v -p /var/cache/httpd/mod_disk_cache -l 100M
Statistics:
size limit 100.0M
total size was 100.0M, total size now 99.9M
total entries was 10060, total entries now 10059
(100.0Mあったのが 99.9Mになるよ。10060個あったのが10059個になるよ。)

元のコンテンツの有効期限をみて器用に削除してもらうのは難しい。

例)今どんなキャッシュが生成されてますか?

# htcacheclean -A -p /var/cache/httpd/mod_disk_cache

phpで実験してみる

引数に渡したテキストをそのまま返すphpで実験する。

実験ではsleepしているだけだが、実際の状況なら、負荷が高くて大変な画像生成処理、集計処理などをしているところを想定していただければ。

<?php
//わざと5秒待たせてから
sleep(5);

//キャッシュしてもらえるヘッダを適切に出力する
header('Last-Modified: ' . gmdate('D, d M Y H:i:s T'));
header('Expires: ' . gmdate('D, d M Y H:i:s T', time() + 36000));

//引数txt=~~に渡された文字列をそのまま返す
header('Content-Type: text/plain; charset=UTF-8');
echo $_GET['txt'];

text.php というファイル名で保存して、Apache側はCacheEnable disk /text.php の設定にしておく。

http://example.com/text.php?txt=123にアクセスすると、
1回目は、5秒たってから、123というテキストが返ってくる。
2回目は、phpで処理しないで、キャッシュされたコンテンツが返ってくるので、即座に123というテキストが返ってくる。

キャッシュがいつまで使われるかは、Expiresヘッダで指定できる。有効期限が1時間後なら、1時間経過するまではキャッシュが使われて、1時間経過後にアクセスがあれば、またバックエンドに問い合わせてくれて、キャッシュは上書きされる。

mod_rewrite環境で

よくあるrewrite設定で、クエリ文字列が見えないように以下のようにURLを書き換えると、期待したようにキャッシュされないので注意。

RewriteRule ^.*$ text.php

php側では $_SERVER[‘REQUEST_URI’] や $_SERVER[‘PATH_INFO’] を見るから不要だとしても、以下のようにURL全体やクエリ文字列なども渡して、引数やパスが違えばrewrite後のURLも異なるようにしておかないと、text.php?txt=1、text.php?txt=2、text.php?txt=3…のキャッシュでなくて、text.phpのキャッシュ1つだけしか作られないことになったりする。

RewriteRule ^.*$ text.php/$0

メモ

mod_cache に似たものに mod_file_cache があるが、これはファイルをキャッシュするもので、動的なコンテンツには使えない。

関連するメモ

コメント