MovableType 標準の検索用スクリプト(mt-search.cgi
)では、検索結果をキャッシュすることで動作速度を向上させていますが、スクリプトが起動してキャッシュ ヒットを調べてしまう時点でパフォーマンスの向上には限界があります。Apache のキャッシュ モジュールなどが使えれば良いのですが、レンタル サーバなどでは制限があったりします。さくらインターネットのレンタル サーバでは、幸い mod_rewrite モジュールの利用が解放されていますので、先日に公開した FileWriter プラグインを利用して、検索結果のうち、タグ検索をより高速にキャッシュ動作するようにしてみました。
mt-search.cgi
でタグ検索を行い、ブラウザに検索結果を返すと同時に、その内容をキャッシュ ファイルに保存します
キャッシュ ファイルが存在しない、最初のタグ検索時(2.)には、mt-search.cgi
が起動し、検索結果をブラウザに返すと同時にキャッシュ ファイルが生成されます。次回のタグ検索以降、1. の動作は Apache がキャッシュ ファイルを静的ファイルとして返すだけで、CGI が起動されることもないため高速に動作します。
FileWriter プラグインは、ブロック内のコンテンツを指定したファイルに書き出します。そこで、検索結果のテンプレート全体を FileWriter ブロック タグで括って、検索結果をファイルに書き出してやります。キーワード検索まで対象にすると、後述の mod_rewrite だけでは処理しきれないので、今回はタグ検索の結果のみをキャッシュするようにしました。
<mt:IfTagSearch> <mt:If tag="SearchResultCount"> <mt:SetVarBlock name="file_writer_path">archive/tag/<$mt:SearchString$>.html</mt:SetVarBlock> </mt:If> </mt:IfTagSearch> <mt:FileWriter path="$file_writer_path"> : 検索結果テンプレート : </mt:FileWriter>
<$mt:SearchString$>
)がファイル名の生成に使われるため、ここで悪意のある入力を防いでいます。
キャッシュが存在する場合には、そもそも mt-search.cgi
が起動されることを防ぎたいので、mod_rewrite モジュールを使って、URL をいい感じにスマートにするついでに、キャッシュが存在するか調べるようにします。
RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^archive/tag/(.+)$ /cgi-bin/mt/mt-search.cgi?blog_id=1&tag=$1 [QSA,L]
キャッシュ ファイルが存在しない場合(1 行目)にだけ、2 行目で mt-search.cgi
が呼ばれます。キャッシュが存在した場合には、キャッシュ ファイルの内容を静的ファイルとして返すだけです。先述の記述では、キャッシュ ファイルは、タグ名.html ですが、Apache の Auto Negotiation 機能によって、拡張子が自動的に補完されます。
キャッシュ ファイルの内容、すなわちタグ検索の結果が変化した際には、キャッシュ ファイルを失効させる必要があります。そのためには、簡易的に、そのタグを付けられたブログ記事/ウェブページが更新されたタイミングで、キャッシュ ファイルを削除します。具体的には、ブログ記事/ウェブページの個別アーカイブ テンプレート内で、そのエントリに付けられたタグ毎に mt:RemoveFile タグを利用して、キャッシュ ファイルを削除します。
<mt:EntryIfTagged> <mt:EntryTags> <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>.html</mt:SetVarBlock> <$mt:RemoveFile path="$cache_path" case_insensitive="1"$> </mt:EntryTags> </mt:EntryIfTagged>
mt:RemoveFile
タグの case_insensitive
オプションは、一見するとよく判らない動作をしますが、これには理由があって、mt-search.cgi
のタグ検索では、タグの大文字/小文字を区別しません。そのため、Amazon や aMaZon でタグ検索をすると、検索結果は同じですが、それぞれ大文字/小文字を区別してキャッシュ ファイルが生成されてしまいます。case_insensitive
オプションは、指定されたファイル名について、こういった大文字小文字の区別なく削除するためのオプションなのです(´・ω・)