Apache2.2のmod_cacheを使って,Wiki(CGI)の高速化を試みる Apache 2.2.3を使用した.
1.基礎知識まずキャッシュをやるなら,
を熟読すべき. 英語だからといって敬遠して俺のように斜め読みしていると,つまらないところではまる. それで結局のところ,パラメータ付きのCGIをキャッシュするには,CGIからの出力に
のヘッダをつけるべきだということがわかる.
2.キャッシュ更新タイミングの考察要件キャッシュの更新タイミングとは,
となる.その観点で考えると,常識的にはせいぜい1日とかになってしまうが,1日だけキャッシュできて嬉しいだろうか? 毎日1回目のリクエストではCGIが実行されてしまうのである. 毎日同じページを更新するような,ページ上書き型更新の場合はそれでも良さそうだが, うちの場合は数日に1回新しいページを作り,そのページは半永久的に更新しないというページ追記型更新であり, この追記したページはそれこそ半永久的にキャッシュして,もう二度とページ生成のCGIが動かないというのが理想である. つまり,
という状態にしておきたい. ただし,Wikiの場合は,ヘッダ,フッタ,メニューという全ページ共通的な要素があり, それらをページ自体とは無関係に更新する可能性があるため, 厳密に半永久だとは言い切れないところもある.
実現方法Apacheがキャッシュを更新するタイミングは,
である *1. 2.について補足すると,このLast-modifiedの条件があるため, Last-modifiedが新しくならない限りはいくらno-cacheのリクエストが来ても,古いページを送り続けてしまうのである. (もちろんmod_cacheのCacheIgnoreCacheControlの設定がデフォルトのoffであっても) それで今回の要件を考えたとき,1.は事前に手動更新するタイミングを予測してExpiresを設定することは不可能なので無理. なので,2.を使い,ブラウザからキャッシュを更新したいページに対して Cache-Control: no-cacheというヘッダがついたリクエストを投げることによって手動更新を実現することを考える. (例えばIEなら,CTRL+F5押下でできる) そして,このときに対象ページでLast-modifiedが新しくなっていることを保証するために, Last-modifiedには,リクエストを受けた時点のシステム日時を設定することとする. ...普通に考えると,
となるのだが, Wikiでは他ページを参照するようなプラグイン(#ls系など)を使っていると, ページ自体は更新されていない(=更新日時が繰り上がっていない)のに表示内容が変わるということがよくあり, その場合でもキャッシュを更新できる必要はある,という考えで,ページの更新日時は使わない. Expiresには,まぁ半永久的な期間を設定すれば良いのだが,とりあえず10日程度としておく. (根拠はない.様子を見てもっと延ばすかも)
3.キャッシュすべきでないコンテンツここまでで,
という状態が実現できたのだが, Wikiの性質として不特定多数がページを編集することを考えると,それら不特定多数の人々に
を徹底できるとは思えない. しかしもしこれが守られなかった場合,自分が編集しようとして見ているページが実はキャッシュが更新されていない関係で古い内容だという状況が発生し, 混乱状態になると思われる. なので,不特定多数が編集可能なページをキャッシュするのは無理な気がしている. カモランドでは,そのような(=凍結状態でない)ページはキャッシュ対象外として
ヘッダを出力しないようにWikiのCGIで制御している. 「凍結状態」で管理者(=俺)しか編集できないページのみを,キャッシュ対象にしている. あと,RSSも更新頻度によるがキャッシュ対象外になりうる.
4.まとめWikiのCGI凍結状態のページへのリクエストに対して,Last-Modified: 現在日時 Expires: 現在日時+10日後(864000秒) のヘッダを出力するようにする.
Apache (mod_cache)<IfModule mod_cache.c> <IfModule mod_disk_cache.c> CacheDirLevels 2 CacheDirLength 1 CacheRoot "/var/cache/apache2/disk_cache/vh1" CacheMaxExpire 864000 CacheEnable disk / CacheDisable /rss/ CacheDisable /blog/index.rdf </IfModule> </IfModule>
5.余談リダイレクトとの関係Caching Guideには冒頭にちゃんと書いてあったのだが,ページに対してRedirectなど別の設定をしても, もしそのページのキャッシュが残っていればそっちが使われてレスポンスを返されてしまう. おかげで,
と長時間ハマった. 結局,キャッシュをディレクトリごと直接消しして解決したのだが,要注意...
mod_deflateとの関係なぜだかよくわからんが,mod_cacheをmod_deflateと併用すると,異様に遅くなった. mod_cacheを使わない場合とほぼ同等の遅さである.そのため,mod_deflateの使用をあきらめる羽目になった.
FireFoxの問題 (2007.04.30追加)普段使わないFireFoxを使った時に気づいたのだが,FireFoxだと普通にリロードしてもno-cacheが効いてしまう.そのため,キャッシュを更新したい時に管理者がno-cacheリクエストを行う(=低頻度)という想定なのに, 現実にはApacheキャッシュの更新が頻発する=CGIの呼び出しがたくさん発生してしまうことが判った. つまり今回の方法だと,FireFoxユーザに対してはあまり意味がないと. そこで仕方がないので,Wiki側でもキャッシュをするという対策を行った. → PyukiWikiにキャッシュ機能をつける |