12月 032013
 

Varnish3.0.5が公開されました。
今回はBugfixですが
varnishlogの-mオプションで動きが変わったため一瞬戸惑うかもしれません。

修正された項目は以下になります。

varnishd

■ESIのパースに失敗した場合に標準出力にメッセージを出していたのをやめました
(Stop printing to stdout on ESI parse warnings)

デバッグの時の消し忘れっぽいですね。

■syntheticの最初のパートでNULLを指定した場合segfaultで落ちるのを修正しました
(#1287)

vcl_error内でstd.filereadを使ってNULLが帰ってきた場合や存在しないヘッダを指定したときなどに出ると思いますが
普通はしないと思います。

■streamを利用した際にContent-Lengthが重複してクライアントに送信されるのを修正しました
(#1272)

重要なFix

■不正なRequestかつvcl_errorでrestartをしている際にクラッシュする問題を修正しました
(#1367 CVE-2013-4484)

この問題はvcl_error内で不正なリクエストをrestartした際に起こる問題です。(リクエスト内容はチケットを参照下さい)
40xや50xを起きた際にrestartを行い別バックエンドなどへのfailoverを行う場合がありますが
その際に不正なリクエストのものをrestartしてしまうとクラッシュします。
バージョンアップでも解決しますが、すぐに行えない場合は以下で回避が可能です


sub vcl_error{
  if (obj.status == 400 || obj.status == 413) {
    return(deliver);
  }
}

このVCLは必ず先頭に書いてください。(vcl_errorが複数あってもOK)
アクションが複数あっても問題ない理由は「同じVCLアクション(vcl_recvなど)を複数定義する」を参照下さい

■クライアントが接続を閉じた後にserver.ipを利用した際にクラッシュする問題を修正しました
(#1376)

varnishadm

■標準入力で渡されたコマンドを適切に扱えなかったのを修正しました
(#1314)

3.0.4(パイプでの渡しが出来ない)


echo vcl.list|varnishadm
200
-----------------------------
Varnish Cache CLI 1.0
-----------------------------
Linux,2.6.32-71.18.1.el6.x86_64,x86_64,-sfile,-smalloc,-hcritbit
varnish-3.0.4 revision 9f83e8f

Type 'help' for command list.
Type 'quit' to close CLI session.

200
active          0 boot

3.0.5(パイプで渡せる)


echo "vcl.list"|varnishadm
200
active          4 boot

一気にpurgeしたいときとか便利ですね。

varnishlog

■-mオプションで絞り込む際に-c若しくは-bを指定しない場合は両方が指定された扱いとなります
(#1071)

3.0.4(-c/-bを指定しなくてもデータが取れる)


varnishlog -m "RxHeader:Host: xcir.net"
...
   12 RxHeader     c Host: xcir.net
...


3.0.5(指定しないと取れない)


varnishlog -m "RxHeader:Host: xcir.net"
^C

varnishlog -m "RxHeader:Host: xcir.net" -c
...
   16 RxHeader     c Accept: */*
   16 RxHeader     c Host: xcir.net
...

今までリクエストヘッダにHost: exmaplnetが含んでいるものを取りたい場合は
varnishlog -m “RxHeader:Host: example.net”
だけでもとれたのですが、
きちんとクライアント<->Varnish(-c)、それともVarnish<->バックエンド(-b)の通信なのかを指定する必要があります。

次は4.0ですね。VUG8でもいろいろ出ていましたが楽しみです
—–
Varnish Cache 3.0.5


11月 302013
 

少し前にサムネイルの作り方をチームの人に聞かれて教えていたのですが
座標の関係がすらすら言えなかったので備忘録的にまとめてみました。
ついでに他の事もまとめてみました。

サムネイルの座標

サムネイルを使う場面はいろいろあると思うのですが大きく分けると2つあると思います。

・単純に小さくする(例:640×480 -> 320×240)
・指定サイズにする(例:640×480 -> 60×60)

単純に小さくする場合はあまり気にしないのですが
指定サイズに収まるようにサムネイルを作る場合は座標を気にする必要があります。

imtg

例えば、上記の例のように縦長の画像を日記のアイコンに使うような正方形のサムネイルにしたい場合において
できれば顔のある可能性が高いあたりをサムネイルとしたいケースがあります。
その場合は何をどのように指定すればよいでしょうか?

image
使う画像処理エンジンによって、呼び名は変わったりするのですが
基本的には上記の例のような関係性が有ります。
先ほどの縦長の画像の上の方をサムネイルに使いたい場合は、元画像のy座標(Source y)を0や縦幅に対して10%のような指定にするとよいでしょう。

また、これらから分かるようにサムネイルの作成は
元画像(Source Image)から切り抜いた画像(crop)を、新しいキャンバス(Thumbnail Image)に指定の座標にリサイズしながら転送するものです。
言い換えると、ケーキ(Source Image)を切り分けて(crop)、個別の皿(Canvas)に載せる(dest)となります。
(この場合はcropのサイズとdestのサイズは同一)
たまにサムネイルのサイズ(canvas width/height)と転送のサイズ(dest width/height)の関係があれ?となる事があると思うのですが、このように覚えるといいんじゃいかなと思います。

また、imagemagickでこのような位置決めをする際に右上とか右下みたいな指定ができます(gravity)
ただnortheastやらsouthwestみたいな指定で日本人的には直感的じゃないかと思いますので図にしてみました。
gravity

長辺・短辺基準

サムネイルを作る際に長辺基準、短辺基準というのが出てきます。
これはどういうことでしょうか?

長方形の画像を正方形のサムネイルにするというケースで考えてみましょう。
当然、長方形を正方形に変更する場合は潰してしまわないとできません。
しかしサムネイルを作る際は、縦横比を変更せずに(=潰さずに)作ることが多いです。
では、縦横比を変更しないで長方形を正方形にするにはどうすればよいでしょうか?
2つの方法があります。

・隙間が空くことを許容して長方形の長い辺がサムネイルのサイズに合うようにする(=長辺基準
s_5
元画像は640×480で、赤い箇所が隙間です

・切り落とされることを許容して長方形の短い辺がサムネイルのサイズに合うようにする(=短辺基準
s_6
長い辺(横)の両端が切り落とされていることがわかると思います。
これが長辺・短辺基準です。

アニメーションgifのリサイズとパレット

今はどうだかわからないのですが、普通に見えていたのにリサイズしてみたら特定の携帯で色が崩れるというケースがありました。(AU端末)
これはどういうことかというと、パレットの持ち方がアニメーションGIF全体で持っているグローバルパレットから、各フレームで持っているローカルパレットに変わったからです。
特定の携帯では、最初のフレームのパレットのみを使い、それぞれのフレームで持っているパレットを無視するため、アニメーションが虹色に見えるといったことが起こります。
これはリサイズする際にギザギザが目立たなくするためにアンチエイリアス処理が走り、使う色が変わったためにグローバルを諦めローカルにしたためです(wikipedia:アンチエイリアス)
また、パレットがグローバルからローカルに変わると、それぞれのフレームでパレットを持つためファイルサイズが増えてしまいます。
こういうことがあるということを知っておくといいかもしれません。

参照:携帯向けアニメーションgifをimagemagickを使ってリサイズする方法(php)

横幅・縦幅のサイズを2倍にした時のファイルとメモリのサイズ

すごく前に、真顔で聞かれて真顔で返したんですが
縦横サイズを2倍にだったらファイルサイズも2倍だろうと言われました。
面積の計算を思い出してください、4倍です。
実際のファイルサイズは圧縮が効いていたりするので一概に言えませんが2倍ではありません。
また表示する際に端末で使うメモリは、基本的に画素数とその1画素で使うサイズが関係するので
640×480で24bitの場合でファイルサイズが50KBの場合でも900KB以上のメモリを使っていると考えていいでしょう。
偶に倍のサイズの画像をブラウザ上で等倍にする人もいますが、こういうことを頭の隅に置いておくといいと思います。

クオリティ

jpegでは画像のクオリティを指定できますがqualityを10にしたからファイルサイズが1/10になるかというとそうではありません。
qual
ちょうどいい画像がなかったので大昔に描いた画像(88,685byte)を
imagemagickでクオリティを1~100で変化させた時のファイルサイズをとってみました。
比例していないのがわかると思います。
また、画像によって傾向は違いますが大体の場合は90ぐらいまでqualityを落とせば高画質とサイズを両立できると思います。

qualst
またいくつかのクオリティで画像がどのような感じになるかです。(im[quality].jpg)

さらにquality=1の画像をquality=100にしてみました。
im1to100
当然の事ながら綺麗になるわけではありません。
JPEGは非可逆であり失われた情報は残っていません。
しかしファイルサイズは増えてしまいます。(3,525byte -> 23,381byte)
クオリティとサイズの関係は覚えておくといいと思います。

RGBとCMYK

これはサムネイルに限った話ではないのですが
偶にブラウザによっては画像の色がおかしく感じる事があります。
cmyk
大体の場合は色の表現方法がCMYKという印刷用のものになっているケースがです。
WebではRGBが基本なので注意が必要です。

ざっくりサムネイルを作るときに知っておくと便利かなとおもったことを書いてみました。
また思いついたら追記するかもしれません。


6月 192013
 

Varnish3.0.4が公開されました。
今回はほとんどBugFixですが、いくつかの機能改善があります。

公式リリースノート(3.0.4)

バグフィックス

CVE-2013-4090 特定条件でACLで想定外のマッチ・マッチ漏れが起こる
#1312
対象は3.0.3までの全てのバージョンです
引っかかる条件は以下だと思います
・CIDR形式の定義が存在(/8,/16,/24を除く)
・単一のIPアドレスを指定している
・その定義範囲が重複している
こんな感じです
VCLコード


acl foo {
  "127.0.0.2";
  "127.0.0.0"/19; //(127.0.0.1 ~ 127.0.31.254で127.0.0.2を含む)
}

Cに変換したコード(3.0.3)


static int
match_acl_named_foo(const struct sess *sp, const void *p)
{
    const unsigned char *a;
    unsigned short fam;

    a = p;
    VRT_memmove(&amp;amp;fam, a + 0, sizeof fam);
    if (fam == 2)
        a += 4;
    else if (fam == 10)
        a += 8;
    else {
        VRT_acl_log(sp, "NO_FAM foo");
        return(0);
    }

    if (fam == 2) {
     if (a[0] == 127) {
      if (a[1] == 0) {
       if (a[2] == 0) {//ここで本来マッチしなくては行けない127.0.1~127.0.31が排除される
        if (a[3] == 2) {
         VRT_acl_log(sp, "MATCH foo " "127.0.0.2");
         return (1);
        }
        VRT_acl_log(sp, "MATCH foo " "127.0.0.0" "/19" );
        return (1);
       }
      }
     }
    }
    VRT_acl_log(sp, "NO_MATCH foo");
    return (0);
}

Cに変換したコード(3.0.4)


static int
match_acl_named_foo(const struct sess *sp, const void *p)
{
        const unsigned char *a;
        unsigned short fam;

        a = p;
        VRT_memmove(&amp;amp;fam, a + 0, sizeof fam);
        if (fam == 2)
                a += 4;
        else if (fam == 10)
                a += 8;
        else {
                VRT_acl_log(sp, "NO_FAM foo");
                return(0);
        }

        if (fam == 2) {
         if (a[0] == 127) {
          if (a[1] == 0) {
           if (a[2] == 0) {
            if (a[3] == 2) {
             VRT_acl_log(sp, "MATCH foo " "127.0.0.2");
             return (1);
            }
           }
           if ((a[2] &amp;amp; 0xe0) == 0) {
            VRT_acl_log(sp, "MATCH foo " "127.0.0.0" "/19" );
            return (1);
           }
          }
         }
        }
        VRT_acl_log(sp, "NO_MATCH foo");
        return (0);
}

影響を受けるかの確認はVCLをCで出してみて
該当のACLマッチ関数(match_acl_named_[ACL名])を見たほうが良いかと思います。

ESI利用時にバックエンドが無効なgzipを送信した場合においてエラーを起こす可能性があった
#1184

バックエンド名が長いとAssertで子プロセスが落ちる
#1224

バグ修正は他にもありますが個人的に気になったのをピックアップしました

ツール改善

varnishncsaのフォーマットで%D,%Tをサポートしました
varnishadmでtabを打つと候補が出るようになりました

パフォーマンス系

TCP_NODELAYを有効にしました(NagleをOffにした)
chunkの時効いてきそうです。

その他

複数のHostヘッダを送られてきた場合はエラーとする
即切断されますのでvcl_recvは呼ばれません(壊れたセッション扱いです)


Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /test HTTP/1.0
Host: exmple.jp
Host: exmple.jp

Connection closed by foreign host.

varnishncsaログ
★ホストヘッダ1つ
127.0.0.1 - - [18/Jun/2013:22:42:40 +0900] "GET http://exmple.jp/test HTTP/1.0" 404 287 "-" "-"
★ホストヘッダ複数
127.0.0.1 - - [18/Jun/2013:22:42:44 +0900] "GET http://exmple.jp/test HTTP/1.0"  - "-" "-"

ドキュメントが改善されました
ABI変わってるのでvmodのリコンパイルが必要

#vug7の記事書く前にこっちの記事を書くことになるとは・・・(下書きにはあるんですがね)


5月 252013
 

みなさんお久しぶりです。いわなちゃんさんです。
最近会社で、「○○さんっていわなちゃんですよね?」と確認されたりしていますが元気しています。

さて、来週の5月30日~31日にかけてニューヨークで行われるVarnish User Group Meeting 7(VUG7)で発表する機会を頂けましたので、先日会社のブログでちらっと触れたレガシーシステムを載せ替えた話といくつか作ったツールについて発表してきます。
本当はVMODの話でもしようかなと考えていたのですが、MLとかIRCを見てて困ってる人が多いのはツールかなと感じたので、そっちの話をしてきます。

ツール自体の記事は、また帰ってきたら書こうと思いますがgithubにはあげていますので見てもらえれば嬉しいです。
あと、ニューヨークで美味しいものを食べたいので、おすすめのお店・ここは見とけといったスポットを教えてもらえると嬉しいです。
飛行機の都合でフリーな時間が多少あるんですが、何処に行こうとかほぼ決めておらず、最悪ホテルに引きこもりかねないので・・・


正直、年初に立てた目標を1つ残して達成してしまったので
今年は順調でもう少し目標追加することを考えています。
残り1つについても見込みが立っていて、多分VUG中に決まるんじゃないかなとか思っています。
色々頑張って行きたいですね


1月 012013
 

なんかTwitterを眺めていたら2012年のまとめみたいな記事が流れてたので僕も書いてみようかなと

大まかな流れ

Varnish尽くし
いやまぁいつも通りですね!
というのはそうなんですが、個人的に大きな出来事は

  • VMODの作成&公開
  • ログ読みツールの作成
  • varnish-miscのMLデビュー
  • 同人誌をVarnishSoftwareに送る
  •  
    です

    VMOD

    VMODは5つほど作成しました。

  • Varnishで簡単にリダイレクトができるVMOD作ってみた(vmod_redirect)@2月
  • X-Forwarded-ForをACLと突き合わせてみる(Varnish)@4月
  • VarnishでPOST・COOKIE・GETを扱うためのVMODを作ってみた(vmod-parsereq)@6月
  • VarnishでAmazon S3の認証ヘッダを作るVMODを作ってみた@7月
  • LDAPで認証したり情報を取得するVMODを作ってみた@8月
  •  
    この中で特に反響が大きかったのがvmod_redirectとvmod_parsereqです。

    vmod_redirectを作った理由はVCLのポリシーを壊さずに拡張するというPoCでした。
    VCLは柔軟性があるし、なんかポリシーなんてあるの?といった感じに思う人もいるかと思いますが
    超えてはならない一線みたいなポリシーを感じる作りになっています。

    僕がそれを顕著に感じたのが、リダイレクトの処理です。
    以下が公式が紹介しているリダイレクトを行うVCLの内容です。

    
    sub vcl_recv {
      if (req.http.user-agent ~ "iP(hone|od)") {
        error 750 "Moved Temporarily";
      }
    }
    
    sub vcl_error {
      if (obj.status == 750) {
        set obj.http.Location = "http://www.example.com/iphoneversion/";
        set obj.status = 302;
        return(deliver);
      }
    }
    
    

    一回VCL_Errorに飛ばして、そこから書き換えてリダイレクトするようなコードになります。
    リダイレクトは利用頻度が(おそらく)高いわけですから
    一つ関数を用意して処理すればいいと考える人も多いと思います。
    しかし、それを許さないところに超えてはならない一線を感じました。

    それならポリシーを壊さずにやってやろうと思って作ったのがvmod_redirectでした。
    目的は1行でVCLのポリシーを破壊せずにリダイレクトまでしてしまうということです。
    実際にユーザ見えではvcl_errorには記述する必要がないのですが
    内部ではフックすることで以下の記述のVCLを動かしています。

    
    sub vcl_error {
      if (obj.status == 301 || obj.status == 302 || obj.status == 303) {
        if(req.http.X-VMODREDIRECT-Location){
          set obj.http.Location = req.http.X-VMODREDIRECT-Location;
          return(deliver);
        }
      }
      /* ユーザが記述したvcl_errorの内容 */
    }
    
    

    正直この手法は穴を突いたものだと感じていて
    バージョンアップでふさがれるのも覚悟したのですが
    MLに投げたところ中々反応がよく、最終的にはVarnishSoftwareが商用サポートしています。
    あっ、許された?と勝手に考え、ここからどんどん他ののVMODを作っています。

    またvmod_parsereqというPOSTなどのリクエストをパースするVMODも作りました。
    これに関しては@dai_yamashitaさんにはかなりご協力をいただき感謝しています。
    初期のバージョンはかなりバグだらけで涙目になったのですが
    さまざまなログ取りをお願いしたり、実際にお会いしてその場でバグ取りもしました。
    おかげさまでいいもの仕上がったんじゃないかなと思っています。
    また、先日ロンドンであったVUG6-DevDayのディスカッションにおいて取り上げられるなど
    正直英語とかで尻込みせずに行っとけばよかったと後悔しました。

    さらにうれしい事にVarnish Security Firewallの一部として使われています。
    実際に使われるまでにはノルウェー・ブラジル・日本(僕)間でディスカッションをしながらやったのですが
    海外のOSSな人とやり取りしながら作っていくという経験は非常に面白くよかったなと思います。
    正直かなり英語でもどかしく感じたので今年こそはスラッとできるように!と決意を新たにしています。
    本当に毎回VarnishSoftwareのRubénさんには助けられまくりです、ありがとうございました。

    ログ読みツール

    varnishlogを見やすくするツールを作ってみた
    varnishlogが見づらいのでそれを見やすくするツールを作ってみました。
    実はこれ元々qpstudyでLTの前座用に作ったモノでした。

    スライドまで作ったのですが何か用事があってqpstudyには行けずにお蔵入りかなーと思ってたんですが
    せっかく作ったし公開するかーと公開してみたらVarnishSoftwareのニュースレターにも掲載されました。
    ニュースレターは購読してるのでメール来て読んでたらいきなり僕の名前が出てきてかなりビビりましたw
    これに関してはかなりコードが汚いので書き直します。
    今年は巳年なのでPythonでーなんて考えていますw

    MLデビュー

    投稿した内容はそこまで多くはないのですが、投稿したおかげで僕が認知されたっぽく
    さまざまな人と交流するきっかけになりました。
    初めての勉強会(qpstudy)に行った時もそうなんですが、最初の一歩はかなり勇気はいるものの
    いざやってしまえば
    「もっと早くやればよかった!」
    と考えています。
    まぁ英語はやらないといけませんが!

    同人誌をVarnishSoftwareに送る

    突然G+の方でVarnish本の現物ってどうやって買うの?といわれて半分混乱しながらEMSで送りました。


    EMSってすごく早いんですね、確か三日ぐらいで届いた気がします。

    まとめ

    去年もVarnishばっかやっていたわけですが(ブログでは)
    全体をまとめると海外デビューというのが大きいです。
    それと同時に英語力が足りないなど様々な自身の問題点に気づいた年でした。
    もっと英語力を挙げてVarnishはもちろんほかのOSSなどでも貢献できればいいなと考えています。

    まぁそんなこんなで今年もどうかよろしくお願いします。


     Posted by at 4:38 AM
    12月 162012
     

    なんとなく突然の死ジェネレータを使って退職しましたと呟いてみたら
    ネタと思われたのか、数人の方から「リアルな話ですか?」とリプライが帰って来ましたが本当に退職です。
    正確には有給消化中で年内は在籍しています。

    僕がクルーズに入社した2009年当時はまだ社名はウェブドゥジャパンでオフィスも麹町で
    ブログ、携帯公式コンテンツなどが主力コンテンツでしたが
    今ではモバゲー向けのソーシャルゲームとコマースを主力でやってます。
    いろいろ環境が激動するなかでコードを書くことはもちろん、
    ネットワークまで幅広い分野で貴重な経験をさせていただきました。

    何やってたの?

    ・社内PHPフレームワーク
    ・画像生成~配信(Varnish)
    ・集計
    ・パフォーマンス関連の調査など
    ・ネットワーク(直近3ヶ月ぐらい)

    など、他にも(Redisとか)やりたい放題を他のエンジニアの協力の下やっていましたが
    軸はフレームをやりつつサービス開発側とインフラ側の間で両者を繋ぐ仕事をしていました(と思ってる)
    開発とインフラが考えていることは最終的なゴールは同じなものの、
    それを行うために意識している点・導き出す手段はかなり異なります。
    その意識していることを両者で共有できて手段を最適化できればその相乗効果は計り知れないです。
    数あるSAPの中ではサーバの台数などは結構頑張ってる方で上手く役に立てたんじゃないかなと考えています
    (もちろんまだまだ改善できる点はあります)

    何で退職するの?

    kamipoさんのつぶやきに触発されたわけではないですが、確かに
    「今の会社では入社して嫌なことがなかったかというと嘘になりますが、本気で嫌で辞めたいと思ったことは一度もありませんでした」
    というのは確かです。
    まぁ、偶に地獄のミサワ風に
    「あー辞めたいわー会社超辞めたいわー」
    という気持ちになることはもちろん有りました。

    主な理由としては
    ・海外でも働けるエンジニアになりたい
    ・技術の幅を広げたい
    があります。

    海外については以前から漠然と考えていましたが、
    Varnish関係で海外の人とやり取りする中で具体的イメージが湧いてきました。
    別に海外で有名になるんだ~ということではなく
    海外でも普通に働けるように様々な技術を身に着けたいなと考えています。
    また、今のクルーズは僕にとっては非常に居心地がよかったのですが
    このままクルーズで働くよりも飛び出したほうが
    自分の技術の幅が広がり、新しいことができるのではないかと考えたからです。
    今年で30ということもあり、攻めるならそろっとやらないとというものありますが。

    最後に

    僕はクルーズで3社目で以前の会社でのキャリアも重要なのですが、
    その中でもクルーズではVarnishに出会う・インフラ・WAFをやるといった様々な事をやり、
    エンジニアである僕を形成するコアなところが作られたと考えています。
    時には失敗もありましたがその後も様々なチャレンジをさせてくれたクルーズに感謝します。

    狭い業界なので勉強会などでお会いすることもあるかと思いますが今後とも宜しくお願い致します。


     Posted by at 5:30 PM
    11月 142012
     

    Varnishは様々なオブジェクトのキャッシュを行いますが
    その際にオブジェクトの保存を何処に行うかを選択することができます。
    現在のバージョンでは

    malloc
    file
    persistent

    といった3つのストレージが存在しており、それぞれに特徴があります。
    今回は特にpersistentに焦点をあてて解説します。

    malloc

    メモリ上にストレージを置いているVarnishで一番高速なストレージです。
    メモリ上に置くため当然のことながらサーバの移設での一時停止や再起動、
    workerのpanicでの自動再起動などでキャッシュが吹き飛んでしまいます。

    file

    ファイル上にストレージを置く、若干遅いストレージです。
    ファイルと名前はついているものの永続化を目的としておらず、
    ストレージへの書き込み時にflushしません。
    読み書きはページ・バッファキャッシュ、つまりOSに任せており
    Varnishでは特に制御はおこなっていないため、オーバーヘッドが少なく高速です。
    正直HDDを使っているときは、あまりおすすめできません。
    しかし、SSDやioDriveといった高速なデバイスの場合は使えるストレージです。

    先程も書いた通り、永続化を目的としていないためmallocと同様に再起動でキャッシュが吹き飛びます。
    名前に騙されてはいけません。

    persistent

    永続化を目的としたストレージです。
    単一のファイルですが、内部では複数のセグメントを持っており
    10~60秒に一回程度でオブジェクトを書き込むセグメントを変更します。
    (ざっくりコードを見た感じだとセグメント変更時もflushをしていない)
    これにより書き込み途中でpanicで自動再起動したとしても、
    壊れたセグメントのみを切り離して再開することができ、安全性が高いストレージです。

    私がV3.0.3でテストしたところ以下の条件でもキャッシュを維持しました。
     ・親プロセスも含めたVarnishの停止・開始(V3.0.0の時は消えましたが3.0.1で修正されました)
     ・varnishadmなどの管理ツールからの停止・開始
     ・panicなどでの自動再起動(一部消えることはある)

    更にVarnish Software公式のアナウンスによるとfileストレージより高速なため
    非常に使ってみたいストレージといえるんじゃないかと思います。

    しかしまだPersistentストレージは発展の途上です。
    最新バージョンである3.0.3では実用上に?がつく残念な仕様が幾つか存在します。

    特にセグメントが一巡した(=指定ストレージサイズを使いきった)際に
    最初のセグメントから再利用するのですが、期限切れしていない場合は再起動を行い拡張を試みます。
    そのため、現時点では非常に玄人向けのマニアックなストレージではないかなと考えています。

    もし私が使うのであれば、
     ・セグメントが一巡することが起因の再起動を起こさせないことが確信できている
     ・最上段ではなく2段目以降
    であれば使うかなーっと言った感じです。

    じゃぁまったく使えないじゃないかというとそうでもなく
    VUG6でのプレゼン資料やVarnish Softwareのブログを見る限り、
    persistentの強化を進めていくように感じられますし
    現在のtrunk(確認したのは2012/11/13バージョン)では再起動も起こらず期待どおりの動きをしています
    恐らく近い将来Varnishの主流のストレージになるのではないかと考えています。
    もちろん人柱覚悟でtrunkを使うのも有りだと思います

    –参考リンク
    Testing the persistent storage engine(Persistentがfileより速いよというベンチ内容)
    Release status(VUG6で発表されたV3.1までのリリース内容)
    ImprovedPersistence(Persistentストレージのマイルストーンについて)
    ArchitecturePersistentStorage(Persistentストレージのアーキテクチャ(古めな内容))


    9月 062012
     

    Amazon S3 REST-API is necessary to generate signature.
    vmod-awsrest generate to Authorization and Date header for Amazon S3.

    How to use

    VCL

    
    import awsrest;
    
    backend default {
      .host = "s3.amazonaws.com";
      .port = "80";
    }
    
    sub vcl_recv{
      awsrest.s3_generic(
      "accessKey",            //AWSAccessKeyId
      "secretKey",            //SecretAccessKeyID
      req.request,            //HTTP-Verb
      req.http.content-md5,   //Content-MD5
      req.http.content-type,  //Content-Type
      "",                     //canonicalizedAmzHeaders
      req.url,                //canonicalizedResource
      now                     //Date
      );
    }
    
    

    Output

    
    15 TxHeader     b Date: Tue, 03 Jul 2012 16:21:47 +0000
    15 TxHeader     b Authorization: AWS accessKey:XUfSbQDuOWL24PTR1qavWSr6vjM=
    
    

    This module set to req.http.Authorization and req.http.Date, bereq is not use.
    I recommend call in the vcl_recv.
    And, be careful to default settings.
    If req.http.Authorization contains, it is not caching. (default setting)

    download here.
    libvmod-awsrest


    Reference site
    PHP で Amazon S3 の REST API を使用 #1
    Authenticating REST Requests

    日本語はこっち
    VarnishでAmazon S3の認証ヘッダを作るVMODを作ってみた


    8月 212012
     

    Varnish3.0.3が公開されました。
    今回の変更は多くのバグフィックスとツール系の機能拡充とドキュメントの整備です。

    公式リリースノート varnish-cache-3.0.3

    バグフィックス

    ・ストリーミングと正規表現の評価においてクラッシュの要因となるバグを複数修正しました。
    ・ESIとGZIPにおいて壊れたオブジェクトを返却するケースが存在する問題を修正しました。
    ・ESIのremoveタグ内にHTMLのコメントがあるケースにおいて不適切な削除を行なっていたのを修正
    ・ban lurkerのスリープする条件の変更(回収した際は設定値・回収しなかった場合は1秒)
    ・多くのクラッシュの要因になるバグの修正
    ・その他いろいろ修正

    ツール系の機能拡充

    varnishstat

    ・json出力オプションの追加(-j)

    varnishtest

    ・resp.bodyでレスポンスボディの評価が可能に

    varnishncsa

    ・VCL中に”Key:Value”の形式でログを出力すると%{VCL_Log:Key}xで取得可能に

    
    ■VCL
      sub vcl_recv{
      std.log("hoge:mage");
    }
    
    [root@localhost ~]# varnishncsa -F "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\" \"%{VCL_Log:hoge}x\""
    192.168.1.199 - - [21/Aug/2012:08:46:27 +0900] "GET http://192.168.1.199:6081/ HTTP/1.0" 200 5 "-" "Wget/1.12 (linux-gnu)" "mage"
    
    
    

    ・%{format}tの対応

    
    [root@localhost ~]# varnishncsa -F "%h %l %u %t \"%r\" %s %b \"%{Referer}i\" \"%{User-agent}i\" \"%{%Y%m%d%H%M%S}t\""
    192.168.1.199 - - [21/Aug/2012:08:51:54 +0900] "GET http://192.168.1.199:6081/ HTTP/1.0" 200 5 "-" "Wget/1.12 (linux-gnu)" "20120821085154"
    
    

    ・formart指定中に\tと\nの指定が可能に

    
    [root@localhost ~]# varnishncsa -F "%h AAA\tBBB\nCCC"
    192.168.1.199 AAA       BBB
    CCC
    
    

    cli

    ・backend.listが追加されました
     バックエンドの状態を確認することができます

    
    ■定義
    director default random{.retries = 5;
      {.weight = 5;.backend={.host="127.0.0.1";.port="81";}}
      {.weight = 5;.backend={.host="127.0.0.1";.port="82";}}
    }
    ■Admin
    backend.list
    200
    Backend name                   Refs   Admin      Probe
    default[0](127.0.0.1,,81)      1      healthy    Healthy (no probe)
    default[1](127.0.0.1,,82)      1      healthy    Healthy (no probe)
    
    

    ・backend.set_healthが追加されました
     バックエンドの状態を強制的に変更できます

    
    ■定義
    backend default {
      .host = "127.0.0.1";
      .port = "81";
    }
    
    ■状態をsickに変更
    backend.set_health default sick
    
    
    
    ■定義
    director default random{.retries = 5;
      {.weight = 5;.backend={.host="127.0.0.1";.port="81";}}
      {.weight = 5;.backend={.host="127.0.0.1";.port="82";}}
    }
    
    ■状態をsickに変更(一つだけ)
    backend.set_health[0] sick
    
    ■状態をsickに変更(全部)
    backend.set_health sick
    
    
    

    パラメータの変更

    ・http_range_support (BOOL default:ON)
     rangeリクエストのサポートですがEXPERIMENTALから正式になりました。
     ただ3.0.0からデフォルトでONになっていたので、特に気にすることはないと思います。

    ・send_timeout (sec default:600)
     送信時のタイムアウト時間が60秒から600秒に変更されました。
     idle_send_timeoutでアイドルの設定ができるようになった影響で増えてると思います。

    ・diag_bitmap (bitmap default:0)
     ban-lurkerのデバッグ用の指定が増えました(0x00080000)

    ・redhat用のsysconfigでVARNISH_MIN_THREADSが1から50に
     デフォルト値がよくなりました

    パラメータの追加

    通信に関わるパラメータ

    ・idle_send_timeout (sec default:60)
     送信時にアイドル状態(データの送信ができなくなった)になった場合のタイムアウト時間です

    内部での正規表現の呼び出しについての制限

    ・pcre_match_limit (1~UINT_MAX default:10000)
     呼び出し回数の制限

    ・pcre_match_limit_recursion (1~UINT_MAX default:10000)
     再起回数の制限

    ドキュメントの整備

    その他変更

    EL6用RPMの用意
    ・DNSディレクターにおいてポートの指定がない場合はデフォルトで80を使うようになった
    ・libvarnishapiの変更
    ・ABIが変わったのでVMODのリビルドが必要
    ・内部関数の定義が変わってるので一部のインラインCやVMODが動かなくなる可能性アリ(HTC_Readが個人的に痛い)

    多くのバグ修正を含んでいるため適用するのが良いかと思います。


    8月 042012
     

    急に、LDAPにアクセスしてみたくなったので、勉強がてら作ってみました。

    よく使われそうな、シンプルなLDAPの認証はもちろん
    特定のグループにだけ許可のようなことも可能です。
    VCLはロジックがかけるので、親和性が高いんじゃないかなと考えています。

    シンプルなLDAPを使ったBASIC認証

    
    import ldap;
    
    sub vcl_error {
      if (obj.status == 401) {
        set obj.http.WWW-Authenticate = {"Basic realm="Authorization Required""};
        synthetic {"Error 401 Unauthorized"};
        return(deliver);
      }
    }
    
    sub vcl_recv{
    
    if(req.url ~ "^/member/"){
            if(!(req.http.Authorization &;amp;&;amp; ldap.simple_auth(
              true, //V3プロトコルで接続するか
              "cn=Manager,dc=ldap,dc=example,dc=com", //バインドアカウント(User)
              "password", //バインドアカウント(Pass)
              "ldap://192.168.1.1/ou=people,dc=ldap,dc=example,dc=com?uid?sub?(objectClass=*)", //LDAP接続先
              ldap.get_basicuser(), //認証したいアカウント(User)
              ldap.get_basicpass()  //認証したいアカウント(Pass)
            ))){
                    error 401;
            }
    }
    
    

    グループとユーザで制限してみる

    
    import ldap;
    
    sub vcl_deliver{
      //LDAPを閉じる
      ldap.close();
    }
    
    sub vcl_error{
      if (obj.status == 401) {
        set obj.http.WWW-Authenticate = {"Basic realm="Authorization Required""};
        synthetic {"Error 401 Unauthorized"};
        return(deliver);
      }
    }
    
    sub vcl_recv{
    
      if(req.url ~ "^/member/"){
            //LDAPに接続
            if(!(req.http.Authorization &;amp;&;amp; ldap.open(
              true, //V3プロトコルで接続するか
              "cn=Manager,dc=ldap,dc=example,dc=com", //バインドアカウント(User)
              "password", //バインドアカウント(Pass)
              "ldap://192.168.1.1/ou=people,dc=ldap,dc=example,dc=com?uid?sub?(objectClass=*)", //LDAP接続先
              ldap.get_basicuser(), //認証したいアカウント(User)
              ldap.get_basicpass()  //認証したいアカウント(Pass)
            ))){
                    error 401;
            }
            //グループの照合
            if(!ldap.compare("cn=test,ou=people,dc=ldap,dc=example,dc=com","memberUid")){ldap.close();error 401;}
            //ユーザの照合
            if(!ldap.require_user("uid=hogehoge,ou=people,dc=ldap,dc=example,dc=com")){ldap.close();error 401;}
            //パスワードの照合
            if(!ldap.bind()){ldap.close();error 401;}
            ldap.close();
      }
    }
    
    

    ちなみにget_basicuserとget_basicpassを使うと
    BASIC認証を行った時に送られてくるAuthorizationヘッダからユーザIDとパスを取得する事ができます。

    なおシンプルな認証で使うsimple_authは内部ではopenとbindとcloseを呼び出しています。

    ダウンロードはこちら(vmod-ldap)