--- layout: old_post title: 「Railsの画面生成を10倍高速化する方法」をESIで実装する permalink: /tatsuya/show/368-rails-10-esi ---

やっと最近余裕が出てきて、溜まってた「あとで読む」リストを消化中ですが、1個面白そうなブログがあったので試してみる

Advanced Rails Caching.. on the Edge

どうも「Railsは重いのでESIでページキャッシュを組み合わせてカバーしよう、ESIのmongrel実装とRails用ESIタグ出力プラグインを開発中だ」と言ってるみたい。発端としては少し前の「 Railsの画面生成を10倍高速化する方法 」このエントリに似た話で

・Railsは遅い、Rubyが遅くてRoutingが遅くてRDBとRHTMLが遅い。

・なので、出来るだけページキャッシュでさばきたい(フロントのWebサーバのみで処理)

・でもユーザ固有情報を表示するのが難しい(ようこそ○○さん)

ここでRails抜きで動的ページを処理するアイデアが幾つか出て来てて

・JavaScript使ってクライアントサイドで動的処理をしようよ派 (現実の世界の Rails、第 2 回: 高度なページ・キャッシング

・サーバサイドで完結させたい派(Railsは基本的なHTMLをページキャッシュとして出力、何らかの手段で二次処理を加える)

 ・SSIを使う(Railsの画面生成を10倍高速化する方法

 ・ESIを使う(Advanced Rails Caching.. on the Edge

等の試行錯誤がされてるみたい。(厳密に言うとESIの人は「更新頻度が少なくても問題無い部分をESIでTTL指定してキャッシュしよう」と言ってる気がするけど気にしない)


ということで、今回はESIを試してみる。ESIのmongrel実装が開発されてるらしいので、まずインストール。

wget http://mongrel-esi.googlecode.com/files/mongrel-esi-0.0.5.gem
sudo gem install mongrel-esi-0.0.5.gem

適当なRailsアプリへ移動し、index.htmlを書き換える。

cd /home/my/rails/app/path
----index.html-----
<h1>Welcome ESI!!</h1>
<p><esi:include src="/welcome/now" max-age="45"/></p>

mongrel_esiを起動

mongrel_esi start
  ** Starting Mongrel listening at 0.0.0.0:2000

ブラウザで http://localhost:2000/index.html を開く、、と例のタグの部分へ 「http://localhost:2000/welcome/now というページが無い」とエラーが出る筈。esi:includeタグ部分へmongrel_esiが外部ページを読み込んでいるので成功。読み込まれるページを用意する

./script/generate controller welcome now
----welcome_controller.rb----
def now
  render :text => "#{Time.now}"
end

再度表示すると、上手く読み込まれる。45秒間キャッシュする設定にしたので(max-age=45)その間は時刻が同じで表示される。これで無事、静的ページへ45秒に1回更新の動的部分を組み込むことができた。

Welcome ESI!!

次はRails用のESIタグ出力プラグイン ”fragmentFu” をインストール、/welcome/index に実装してみる

./script/plugin install http://mongrel-esi.googlecode.com/svn/trunk/plugin/fragment_fu
----/app/view/welcome/index.html.erb----
<h1>Welcome ESI!!</h1>
<p><%= render :esi => {:action => "now"}, :ttl => 45.seconds %> </p>

これで上でhtmlに記述したタグと同じESIタグが出力される。あとはこれをページキャッシュに指定すればOK。但し「ようこそ○○さん」等のユーザ固有処理を行うためにはSSIと同じようにESI + PHPを組み合わせる等工夫が必要になるかもしれない。ちなみにESIではCookieの値や、クエリーストリングなんかを処理に組み込めるので

#クエリーストリングをページ読み込みのURLに利用
<p><%= render :esi => "/users/name/$(QUERY_STRING{my_name})" %> </p>
#Cookieをページ読み込みのURLに利用
<p><%= render :esi => "/users/home/$(HTTP_COOKIE{UserID})" %> </p>

等、動的に読み込む外部ページのURLを変えることである程度「Rails & 2段階のページキャッシュ」で完結できる、かも。まあ別にSSIだろうがESIだろうが結局は何でも良いんだけど、しいていうならコードはRailsで完結させたいな。さらに理想を言えば

初回)/welcome/index と /users/show/ユーザID/name をページキャッシュ

初回以降)/welcome/indexの静的ページキャッシュへ、 /users/show/$(HTTP_COOKIE{UserID})/name のページキャッシュをESIで動的読み込み(ようこそ○○さん)

ユーザが名前を変更)/users/show/ユーザID/name をキャッシュ作り直し

(他のページからも /users/show/ユーザID/name を利用するがキャッシュは一つ)


というのがやりたい。Rails出力は初回のみにして基本ページキャッシュを表示する、しかもmongrel + Railsな手慣れたツールで完結させたい。もう少し考えてみよう。

参考リンク

W3C ESI Language Specification 1.0 ESIのW3C仕様

FragmentFu - Fun with Fragments mongrel_esiとRailsの連携、チュートリアル有

現実の世界の Rails、第 2 回: 高度なページ・キャッシング JavaScriptでページキャッシュを2次処理

Railsの画面生成を10倍高速化する方法 SSI + PHP でページキャッシュを2次処理

Oracle - Edge Side Includes用のJESIタグ ESIのOracle Application Server実装資料