CGI 出力キャッシュ

mod_mem_cache で負荷軽減

CGI 等で生成される動的コンテンツには,個別のリクエストごとに異なるレスポンスを 返さなければならないものもあれば,ある程度の時間内であればどのリクエストに 対しても同じレスポンスを返すものもあるでしょう.後者であれば,レスポンスを mod_mem_cache でキャッシュすることにより毎回 CGI 等を実行せずに済むので, かなり効果的にサーバの負荷軽減を実現することができます.

# mod_mem_cache は Apache 2.0 ではまだ "experimental" という扱いですが, Apache 2.1 / 2.2 ではかなり改良されています.

httpd.conf での設定は,例えば以下のような感じで.動的コンテンツでは Content-Length ヘッダを出力しないことが多いですから,MCacheMaxObjectSize の指定に際しては併せて MCacheMaxStreamingBuffer も指定しましょう.

LoadModule cache_module modules/mod_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so

<IfModule mod_mem_cache.c>
    CacheEnable mem /cgi-bin/
    MCacheSize 256000
    MCacheMaxObjectSize 128000
    MCacheMaxStreamingBuffer 128000
</IfModule>

なお,mod_mem_cache は各 httpd プロセス単位で個別にキャッシュを保持します. 従って,マルチスレッド MPM を用い,かつプロセス数を絞って1プロセスあたりの スレッド数を多くする設定の方が,効果的にキャッシュが利用されます.

Last-Modified ヘッダ及びそのチェック

動的コンテンツを mod_mem_cache でキャッシュさせるには, Last-Modified ヘッダを出力すべきということになります. Last-Modified なしでも CacheIgnoreNoLastMod ディレクティブで 対応することもできなくはないですが,コンテンツの更新を 正しく検出するためにはやはり Last-Modified が必要です.

Last-Modified として指定する日時をどうするかについては, 例えばデータをファイルに格納しているなら,そのデータファイルの mtime(更新日時)を利用するのが最も簡単でしょう.データを DB に格納しているなら,処理内容や出力コンテンツ等に応じて, データテーブルの更新日時を記録するテーブルを新たに設けるとか, あるいは各レコード単位の更新日時を記録するフィールドを データテーブルに追加する,等という方法が考えられます.

Last-Modified ヘッダの出力方法やそのチェック方法については, mod_cgidsoを用いる場合なら,そこで例示している サンプルコードを参照して下さい.

Cache-Control ヘッダ

動的コンテンツをキャッシュさせる場合,更新チェックのタイミング等を きめ細かく制御したい場合もあるでしょうし,また,キャッシュさせたくない コンテンツもあるでしょう.そのような制御には Cache-Control ヘッダを用います.

Cache-Control ヘッダがない場合,「(遅延等も加味したキャッシュ保持時間) < (コンテンツ取得時点での Last-Modified からの経過時間) × (CacheLastModifiedFactor ディレクティブ指定値 (デフォルト: 0.1))」 であれば更新チェックを行わずキャッシュの内容を返し,そうでなければ 更新チェックを行います(更新されていなければキャッシュの内容を返します). 以下,Cache-Control ヘッダ指定の例をいくつか挙げてみます.

遅延等も加味したキャッシュ保持時間が20秒未満なら更新チェックを行わず キャッシュの内容を返し,20秒以上経過していれば更新チェックを行う場合 (更新されていなければキャッシュの内容を返す):

Cache-Control: s-maxage=20

常に更新チェックを行う場合(更新されていなければキャッシュの内容を返す):

Cache-Control: s-maxage=0

mod_cache でのキャッシュを行わない場合(ブラウザのキャッシュは行われる):

Cache-Control: private

mod_cache・ブラウザともにキャッシュへのデータ格納を一切行わない場合:

Cache-Control: no-store

上記の例で,s-maxage の指定は mod_cache の動作に影響しますが ブラウザには影響しません.ブラウザも含め制御したい場合は 代わりに max-age を用います.

Basic / Digest 認証を用いている場合,デフォルトではキャッシュされません. ただし,Cache-Control で s-maxage / must-revalidate / public のいずれかが指定されていればキャッシュされます.