タグクラウドの高速化

1.検討

mt-search.cgi速度問題はMTの課題のようですが、特にwebkoza.comのように非力なサーバー環境ではかなりのボトルネックとなっていました。なにせ表示までに10秒以上かかることがあるのですから。。それでもたまにタグクラウドは利用されているようなので、何とかこれだけでも早くできないものかと考えて調べてみたところ、サーチエンジンを作り直す以外に、利用できそうなプラグインがあることがわかりました。現在3種類ぐらいあるようです。 それぞれの特徴を私なりに簡単にまとめてみました。

alfasado/mt-plugin-build-cache プラグイン

リクエストされたときにサーバーサイドに表示データをキャッシュさせるプラグインです。他のプラグインよりもかなり汎用的に作られているようです。MTコミュニティやCMSの世界ではかなり有名な方の会社alfasadoが作ったものですが、まとまったドキュメントが見つけられず、私には敷居が高い感じです。

flexibleSearch.js プラグイン

あらかじめ登録されたJSONデータをブラウザサイドにプリロードしておくことにより、検索作業は実質ブラウザサイドで行われるそうです。プラグイン自体はJQueryを使用したJavascriptコードです。作者のGit-HubレポジトリのReadmeには、プリロードされるJSONデータを出力するテンプレートが紹介されているので、設置の参考になりそうです。用意するJSONデータの内容次第ということになりますが、うまく作れば威力絶大だと思います。

FileWriter プラグイン

リクエストされたときにサーバーサイドに表示データをキャッシュさせるプラグインです。作者の記事がわかりやすく、比較的簡単に設置できそうだったので採用しました。書き出すための設定は簡単で、検索結果テンプレート全文を、キャッシュを書き出すためのブロックタグで囲むだけです。記事が更新されるか新規投稿された時にキャッシュをクリアするには、記事アーカイブテンプレートの最後に、キャッシュクリアするためのタグを使用して、ファイルを削除するコードを埋め込みます。キャッシュが無い場合のみmt-search.cgiを実行するようにするためには、apoacheのmod_rewriteを利用します。

というわけでFileWriterプラグインを採用し、お茶の間のタグクラウドについてはほぼストレスフリーになりました。ぜひお試しください。設置にあたり、工夫した点もあるので、一通り記事にしてみます。

なお、上述した作者のサイトを参考にしています。

2.FileWriterプラグインの概要

このプラグインは、「MTFileWriter」、「MTRemoveFile」という2つのMTタグを提供するプラグインです。前者はそのブロックタグで囲んだテンプレートの出力結果をキャッシュとしてファイルに出力し、後者は、記事アーカイブテンプレートの最後などで使用して、そのテンプレート出力があった時に指定したファイルを削除します。

このプラグインで生成されたキャッシュが無い時だけ、mt-search.cgiを実行するようにするには、apacheのmod_rewriteなどを利用します。

インストールはmt/pluginディレクトリ配下にコピーするだけです。インストール後に実施した設置手順は下記です。工夫した点としては、タグクラウドのリンクを変更することなしに設置した点です。検索してみるとタグクラウドのリンクURLは全てgoogleに登録されていたので。

3.検索結果テンプレートの改変

検索結果テンプレートをMTFileWriterタグで囲んで、その外側の最初の部分にMTFileWriterのモディファイアで指定するファイル名パスを指定します。ここではIfTagSearchを使用してタグ検索の時にタグ名を使用したファイル名を指定できるようにしています。

<mt:IfTagSearch>
  <mt:If tag="SearchResultCount">
<mt:SetVarBlock name="file_writer_path">archive/tag/<$mt:SearchString replace="/",""$>_<$MTCurrentPage$>.html</mt:SetVarBlock>
  </mt:If>
</mt:IfTagSearch>
<mt:FileWriter path="$file_writer_path">

<!DOCTYPE html>
<html lang="<$mt:BlogLanguage$>">
  <head>
・・・・
  </body>
</html>
</mt:FileWriter>

<$mt:SearchString replace="/",""$>_<のreplaceモディファイアは、なぜかタグクラウドのタグ情報に/が付加してしまうことが有ったのでこれで削除できるようにしました。(後述)

4.キャッシュが生成されることの確認

検索結果テンプレートを保存して、タグクラウドのリンクをクリックすると上記で指定した場所にキャッシュとしてhtmlファイル(検索結果ページ)が生成されることを確認しました。ちなみに、タグクラウドは、検索botに拾ってもらいやすくするために、apacheのmod_rewriteを使用して下記のようなURL変換を行っていました。

/rooms/tag/(タグ名)/ → /mt/mt-search.cgi?IncludeBlogs=7&tag=(タグ名)&limit=20

このためにhttpd.confに下記の通り記述

RewriteEngine on
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{SCRIPT_FILENAME} !-f
RewriteRule ^/rooms/tag/(.+)/?$ /mt/mt-search.cgi?IncludeBlogs=7&tag=$1&limit=20

これだとなぜか、$1の末尾に「/」が付いてしまうという不思議な現象がありました。でもこれは無視されて検索には影響されません。今まではこれでよかったのですが、このストリングを基にキャッシュ先を決めなければならないので都合が悪いわけです。そこで上述のとおり、キャッシュ先ファイル名を決めるSearchStringタグにreplaceモディファイアを使って/をヌルに置換することで解決しました。

5.キャッシュが削除されるための設定

ブログ記事の新規投稿または更新時にキャッシュファイルを削除するようにするには、ブログ記事アーカイブテンプレートの最後に、MTRemoveFileタグを使用したコードを記述します。検索結果は1ページ最大20アイテム表示しますので、40アイテムを超える場合は3ページ分、20アイテムを超える場合は2ページ分、それ以下は1ページ分削除するようにしました。最後に再構築しておきます。

・・・
</html>
<mt:EntryIfTagged>
  <mt:EntryTags>
    <mt:setvarBlock name="tagCount"><$MTTagCount$></mt:setvarBlock>
    <mt:If name="tagCount" gt="40">
      <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>_1.html</mt:SetVarBlock>
      <$mt:RemoveFile path="$cache_path"$>
      <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>_2.html</mt:SetVarBlock>
      <$mt:RemoveFile path="$cache_path"$>
      <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>_3.html</mt:SetVarBlock>
      <$mt:RemoveFile path="$cache_path"$>
    <mt:ElseIf gt="20">
      <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>_1.html</mt:SetVarBlock>
      <$mt:RemoveFile path="$cache_path"$>
      <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>_2.html</mt:SetVarBlock>
      <$mt:RemoveFile path="$cache_path"$>
    <mt:ElseIf le="20">
      <mt:SetVarBlock name="cache_path">archive/tag/<mt:TagName>_1.html</mt:SetVarBlock>
      <$mt:RemoveFile path="$cache_path"$>
    <mt:Else></mt:If>
  </mt:EntryTags>
</mt:EntryIfTagged>

6.キャッシュが削除されることの確認

上記設定をした後、1つの記事を更新してみて、その記事に設定しているタグのキャッシュファイルが削除されることを確認しました。

7.キャッシュが無い時だけmt-searcg.cgiに飛ばす

このままだと、
/rooms/tag/(タグ名)/ → /mt/mt-search.cgi?IncludeBlogs=7&tag=(タグ名)&limit=20
という設定がされているので常にmt-search.cgiが実行され、<mt:FileWriter>により常にキャッシュファイルが生成(上書き)されてしまいます。これでは意味が無いので、URL Rewriteの設定を変更する必要があります。しかし、方針として前述したようにタグクラウドリンクURLは変更したくないので、少し工夫しました。 ここでやりたいことは、
/rooms/tag/(タグ名)/ → /rooms/archive/tag/(タグ名)1.html ファイルが 
[存在しなければ]→ /mt/mt-search.cgi?IncludeBlogs=7&tag=(タグ名)&limit=20の結果をレスポンス 
[存在してれば]→ /rooms/archive/tag/(タグ名)1.html をレスポンス

そこでapacheの設定で2段階のURLリダイレクトを行うことにしました。まず、タグクラウドリンクURLをmodaliasRedirectMachディレクティブを使って、対応するキャッシュファイルにリダイレクトします。次にmodrewriteのRewriteRuleを使って、キャッシュファイルが無い時だけmt-search.cgiにリダイレクトします。具体的には下記

<httpd.conf>

RedirectMatch /rooms/tag/(.*)/$ /rooms/archive/tag/$1_1.html

<.htaccess>

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^rooms/archive/tag/(.+)_1\.html$ /mt/mt-search.cgi?IncludeBlogs=7&tag=$1&limit=20

後で知ったのですがRedirectMactchディレクティブも.htaccess内で使用できるようです。

8.キャッシュデータ有無によるmt-search.cgiの動作確認

ここまでで、当初の目的を果たすことができました。すなわち、タグクラウドリンクをクリックして、キャッシュデータが無い時はmt-search.cgiが起動して検索結果が表示され(数秒待たされる)、キャッシュデータがある時はキャッシュを即表示します。ほんとこの速度差は圧倒的です。