httpdでcacheする apache編
※このエントリは微妙に自力ではありません
webアプリを運用していて、静的・動的問わず
- 転送量がやばい
- 負荷がやばい
- そのせいで誰かがやばい
などといったときがあることもあって、普通はmemcachedなりsquidなりを使うけど、
などのケースが有ったり無かったり。
で、静的コンテンツをhttpdでさくっと対処する場合の話。
apacheだったらそこでmod_cache。
mod_cacheにはディスクに記憶するmod_disk_cacheとメモリに記憶するmod_mem_cacheがある。
静的コンテンツならmod_disk_cache、動的コンテンツ・リバースプロキシならmod_mem_cacheが定石らしい。
設定内容
例えば /images/ 以下のファイルをキャッシュする場合。
<IfModule mod_disk_cache.c> CacheEnable disk /images/ CacheRoot /dev/shm/mod_cache CacheDefaultExpire 3600 CacheIgnoreCacheControl On CacheIgnoreNoLastMod On CacheDirLevels 1 CacheDirLength 1 </IfModule>
で、ディレクトリ作ってやる。
% sudo mkdir /dev/shm/mod_cache % sudo chmod 777 /dev/shm/mod_cache
本当はディレクトリはこんな権限777じゃなくて、apacheを動かしているユーザ・グループで作るべし。
キャッシュをr/wするのはapacheを動かしているユーザなので。
777だとrootにならなくてもディレクトリにcdできるし中見るのも楽だわーとかになるので俺は個人的に777にしているだけである。
セキュリティホールになる気がしなくもない。
大体はマニュアルに載っているのだけど。
CacheEnable
http://httpd.apache.org/docs/2.2/ja/mod/mod_cache.html#cacheenable
キャッシュするパスと、mod_disk_cache/mod_mem_cacheのどちらを使うか指定する。
fdを指定した場合がマニュアル見てもいまいち分からないが多分必要になることは無い気がするのでYAGNIの精神で華麗にスルー。
CacheDirLength / CacheDirLevels
http://httpd.apache.org/docs/2.2/ja/mod/mod_disk_cache.html#cachedirlevels
cacheするのに使うディレクトリの階層と長さと。キャッシュするファイルが少なければどっちも1でいいだろう。
多くなったら…YAGNIの精神で略。
CacheRoot
http://httpd.apache.org/docs/2.2/ja/mod/mod_disk_cache.html#cacheroot
キャッシュするディレクトリを指定する。apacheは作ってくれないから手動で作る。
どうせなら物理ディスクよりもtmpfsを使った方がディスクio減るんじゃないかと。
そういえばtmpfsとramディスクってどっちが性能いいんだっけ。
CacheDefaultExpire
http://httpd.apache.org/docs/2.2/ja/mod/mod_cache.html#cachedefaultexpire
キャッシュする時間。内容が変化しない静的コンテンツなら巨大な値でもいい。
CacheIgnoreNoLastMod
http://httpd.apache.org/docs/2.2/ja/mod/mod_cache.html#cacheignorenolastmod
Last-Modifiedが無かろうとキャッシュする。ご丁寧にLMつけてるケースの方が少ない気がする。
CacheIgnoreCacheControl
http://httpd.apache.org/docs/2.2/ja/mod/mod_cache.html#cacheignorecachecontrol
個人的にはこれがハマりどころ。
ヘッダでCache-Control: no-cache や Pragma: no-storeがあってもキャッシュを返す。
俺はfirefoxでリロードして設定を確認するのだけど、どうもfirefoxさんのリロードはスーパーリロードか何かになっているらしく、mod_cacheがキャッシュを作ってもそのキャッシュを使わない。
アクセスログも304ではなく200が返る。それじゃ困るんですよ。
キャッシュの動作
これで例えば /images/hoge.jpg とかにアクセスするとこんなファイルが出来る。
% find /dev/shm/mod_cache/ -type f /dev/shm/mod_cache/6/KXf3h0Y6M8uQNrbWN0eyA.data /dev/shm/mod_cache/6/KXf3h0Y6M8uQNrbWN0eyA.header
※ここからうそ臭いです
キャッシュファイルのプロセスはこう。
- アクセスされたらキャッシュファイルが生成される
- 生成されてからCacheDefaultExpireで指定した秒数が経過するまでは、アクセスが来てもキャッシュがコンテンツを返し、実ファイルにはアクセスがいかない
- CacheDefaultExpire秒が経過しても、キャッシュファイルは削除されない。次のアクセスがきて初めて削除される。そして新しいキャッシュファイルが生成される。
なので、沢山のファイルにアクセスされた後に、コンテンツ一新などしてそのファイル全てがアクセスされなくなると、削除されないキャッシュファイルがたくさん残る。
手動でキャッシュを削除してやってもいいやも。
以下をcronで実行するとか。
find /dev/shm/mod_cache -type f -exec rm '{}' \;
todo
「httpdでcacheする nginx編」を書く