VarnishではじめるESI
     2012/03/29
  いわなちゃんさん(@xcir)
自己紹介
●   いわなちゃん(さん) (@xcir)
●   ソーシャルゲームをやってる会社で
    VarnishやらC#やらPHPやったり
●   六本木にいます
●   アルパカが好きです
●   会場がCAなのでアメーバ水が欲しいです!!




       絡んでくれると喜びます!
キャッシュって要は静的コンテンツ
  しか適用できないよね?




 CSSとかJavascriptとか画像とか・・・
キャッシュって要は静的コンテンツ
  しか適用できないよね?




 いいえ(半分)違います。
そもそも静的コンテンツってなんだろう


               画像?
 HTML1枚のページ?




               CSS?
そもそも静的コンテンツってなんだろう




     LLで生成したページは
        動的?静的?
動的?静的?
            ブログ名を
           変更するまで
             静的

                      管理ページで
                      変更するまで
                        静的




  新しい投稿が            新しい投稿が
  あるまで静的            あるまで静的
動的?静的?



実は多くの動的とされている
コンテンツは静的コンテンツの
   組み合わせが多い
動的?静的?
         ログインユーザ
          ごとに静的
動的?静的?




やっぱり静的の組み合わせ
動的?静的?


     +

     +                 +

 +       +         +       +




Aさんの要求するページ       Bさんの要求するページ
動的?静的?



   ユーザによって
  出る内容が違うのなら
ページをキャッシュ出来ない?
動的?静的?



 こういう場合はプログラム側で
キャッシュしたりして組み立てたり
    することが多いです
    (Memcacheとかで)
ESI! ESI! ESI!



    ページ全体でキャッシュ
      できないのなら
要素ごとにキャッシュすればいいじゃない!
ESIとは
            (Edege Side Includes)



  2001年にAkamaiやOracleなどが策定
Webページの要素を動的に構成する仕組み
          http://www.w3.org/TR/esi-lang



特殊なタグをコンテンツに埋め込んで使う
          <esi:include src=”url”>
     指定URLからコンテンツを取って埋め込む

                   などなど
       Varnishは一部のタグのみサポートしてます
VarnishでESI!




               Aさんの要求するページ

   要素を結合




               Bさんの要求するページ
VarnishでESIを使ってみよう
default.vcl                                  esi.html
------------------------------------------   ------------------------------------------
backend default{                             <html>
       .host="localhost";                    <body>
       .port="81";                           20sec <esi:include src=”/a.php”>
}                                            2sec <esi:include src=”/b.php”>
                                             </body>
sub vcl_fetch{                               </html>
     set beresp.do_esi = true;
}
                                             a.php
                                             ------------------------------------------
                これだけで有効に                     <?php header('Cache-Control: max-age=20');?>
                                             <div>
                                             <?php echo date('Y/m/d H:i:s');?>
                                             </div>


                                             b.php
                                             ------------------------------------------
                                             <?php header('Cache-Control: max-age=2');?>
                                             <div>
                                             <?php echo date('Y/m/d H:i:s');?>
                                             </div>
VarnishでESIを使ってみよう

Apache直
                   Varnish経由




             20secと2secの時刻がずれているので
             キャッシュされているのがわかる
ねっ




簡単でしょ?
VarnishでESIを使う理由

今回のは明示的にmax-ageを指定しましたが
     実際はテンプレートで
   キャッシュ時間を指定したい!
         (こんな感じで)
              esi.html
              ------------------------------------------
              <html>
              <body>
              20sec <esi:include src=”/a.php?ttl=120s”>
              2sec <esi:include src=”/b.php?ttl=10s”>
              </body>
              </html>
                                     VCLで拾ってTTL設定も簡単


  などなど細かい制御が容易な
    Varnishがおすすめ!
ESIは銀の弾丸ではない
     素晴らしいESIですが
 入れれば即100倍界王拳とは行きません

         たとえば
キャッシュができないコンテンツ(携帯での広告)
    極端に更新間隔の短いコンテンツ
          etc...
   いろいろ適用が難しい場合もあります

    キャッシュの一つの手段として
     考えてもらえば幸いです
VarnishでESIで使う際の注意

 ESIの解釈が行われるためには
   コンテンツの最初が「<」で
    始まる必要があります

 もしこれ以外で行いたい場合は
       起動パラメータに
  -p esi_syntax=0x00000001
       を付与してください
VarnishでESIで使う際の注意



   ユーザー毎に出しわけをする
        要素を含む場合は
必ずvcl_hashでその値を追加してください
     でないと全てのアクセスで
 同じ結果が出るという悲しい事態に・・・
         Varnishはオブジェクトを特定するのにHashを使います
そのHashを生成するキーにユーザIDを含めるようなイメージです(クッキーから抽出とか)
VarnishでESIで使う際の注意



  ESIの要素が複数ある場合
 今のバージョンのVarnishでは
 並列ではなく逐次取得します
    (将来は対応するみたいです)
VarnishでESIで使う際の注意

ESIはセッションワークスペースを
    たくさん使用します
  そのためデフォルト値(64k)
 では足りない可能性があるので
  大きめに指定すると良いです
例えば5MBとか指定しても100KBしか使わなければ
      実使用サイズは100KBです
VarnishでESIで使う際の注意



    ESIの要素がエラーで
   アクセス出来ない場合に
     こうならないように
     エラー時の挙動を
   制御したほうがよいです
VarnishでESIで使う際の注意
default.vcl
------------------------------------------
import std;
backend default{
       .host="localhost";                       /tmp/hoge.txt
       .port="81";                              ------------------------------------------
}                                               もう眠いです(:3[__])

sub vcl_fetch{
     if(beresp.status>=400){
           error(beresp.status);
     }
     set beresp.do_esi = true;
}
sub vcl_error{
     synthetic std.fileread("/tmp/hoge.txt");
     return(deliver);
}




                      たとえばこんな感じでエラーを埋め込むとか
                      (VCL内でマルチバイト文字を入れると化けます)
ご清聴ありがとうございました

VarnishではじめるESI