最速SuperCache

最近Symfonyのプラグインの中で個人的に気になっているのがsfSuperCacheです。Symfonyには元々cacheのメカニズムが組み込まれていますが、sfSuperCache別のアプローチでキャッシュします。Symfonyに組み込まれたcacheの仕組みは、myproject/cache等のディレクトリにアクションやコンポネントの実行結果を保存しておき、次回のリクエストの時アクションやビューの処理を飛ばす事で実行速度を上げています。sfSuperCacheでは、キャッシュの結果をmyproject/cacheではなくmyproject/web/cache以下に保存し、Apacheのmod_rewriteを利用してPHPを仲介せず直接静的なコンテンツを呼びにいきます。つまり、sfSuperCacheはSymfonyの巨大なフロントコントローラを介さない事で一桁違う処理スピードを実現するのです

ちょうどディノのホームページをウェブプロダクションに制作依頼していますが、このウェブをSymfonyベースのCMS(コンテンツ管理システム)にしようと思っています。企業のホームページは静的な部分が多いのでsfSuperCacheは是非多用したいプラグインです。

本家tracにある文章に注釈を加えながら説明してきます。(というか、1.0.0-betaではこの通りやったのではさっぱり動きません)

インストール

プロジェクトディレクトリにてプラグインをインストールします。sfSuperCacheに限った事ではないのですが、1.0.0-betaでプラグインをインストールする時に、

symfony plugin-install http://plugins.symfony-project.com/sfSuperCachePlugin

本家tracでは上のコマンドでプラグインをインストールしていますが、私のMacOSXではうまく行きません。sudoとするとなぜかうまく行きます。

sudo symfony plugin-install http://plugins.symfony-project.com/sfSuperCachePlugin

web/cacheディレクトリの作成

次にキャッシュを保存するweb/cacheディレクトリを作成します。ついでに、Subversionの管理から除外するためにsvn-addignoreをしておきます。

mkdir web/cache
chmod 777 web/cache
svn-addignore web/cache

余談になりますが、私はSubversionからチェックアウトした後、実行環境をセットアップするスクリプトをmyproject/bootstrapというファイル名でおいています。bootstrapにもweb/cacheの作成作業を追加しておきます。bootstrapファイルの中身は以下のようになっています。

#!/usr/bin/env bash
mkdir -p cache log web/uploads/assets web/cache
symfony fix-perms
chmod 777 web/cache

filters.ymlに追加する

以下のようにfilters.ymlに追加します。追加というは嘘です(ごめんなさい)上に足してください

supercache:
   class: sfSuperCacheFilter
   param:
     cache_dir: cache
rendering: ~
web_debug: ~
security:  ~
cache:     ~
common:    ~
flash:     ~
execution: ~

sfSuperCacheは、PostFilterですので下に足したのでは他のフィルターの実行結果が反映されません。SymfonyではcommonフィルタでStyleSheetが追加されるのですが、filters.ymlの最下部にsfSuperCacheを記述するとStyleSheetが適用され無い状態でキャッシュされてしまいます。

.htaccessの修正

    RewriteRule ^$ index.html [QSA]
    RewriteRule ^([^.]+)$ $1.html [QSA]

の部分を以下のように修正します。

    # if the request starts with /cache
    RewriteCond %{REQUEST_URI} ^/cache
    # and it's not the user that requested this in his browser
    RewriteCond %{THE_REQUEST} !/cache/
    # go
    RewriteRule .* - [L]
 
    # check the page in the "super" cache
    RewriteRule ^$ index.html
    RewriteRule ^(.+)/$ $1/index.html
    RewriteRule ^(.*)$ cache/%{HTTP_HOST}/$1

prod環境のフロントコントローラを作成

sfSuperCacheには以下のような発動条件があります。

  • デバッグモードが無効であること
  • レイアウトを含んだキャッシュ 有効であること
  • GET/POSTのパラメータないこと
  • no_script_name であること
  • HTTPのレスポンスが成功(200)であること

つまり、prod環境にしろということですのでprod環境のcontrollerをつくります。init-controllerについては以前のエントリに説明がありますので参考にしてください。

symfony init-controller frontend prod index false

cacheを有効にする

発動条件を合わせるためmyproject/apps/frontend/config/cache.ymlを以下のように変えます。

default:
  enabled:     on
  with_layout: true
  lifetime:    86400

myproject/apps/frontend/config/settings.ymlも以下のように変更します。

prod:
  .settings:
    no_script_name:     on
    cache:                  on
    suffix:                  .html

clear-cache

フロントコントローラと設定ファイルを替えたのでキャッシュをクリアします。

symfony cc

お疲れさまでした

ここまでの作業でsfSuperCacheが動くはずですのでブラウザから試してみます。http://localhost/ をリクエストしてみます。myprojecct/web/cache/localhost/index.htmlが生成されていればとりあえず成功です。次にもう一回http://localhost/にアクセスしてください。同じ画面が出ましたか?これでは本当に動いているか不安ですね。ちゃんと動いているか確かめる為に思い切ってフロントコントローラを叩き消してしまいましょう。

rm web/index.php

この状態で動けばきちんと動いていると信じられますね。

制限事項と補足説明

sfSuperCacheで生成されたキャッシュはsymfon ccコマンドではクリアされません。手動でweb/cacheを消して上で紹介したbootstrapで再生成するといいでしょう。また、キャッシュはWebサーバからは完全に静的なファイルとしてあつかわれるのでContent-Typeを決定する上で拡張子(.html)が必ず必要です。

sfSuperCacheは非常に簡単な仕組みですがうまく適用できれば効果は絶大です。機会があったら是非どうぞ。

Leave a Reply

You must be logged in to post a comment.