4月 022017
 

5.0.0の後継の5.1.1がリリースされました。 [changelog] [リリース文] [changes] [Upgrading]
また、今回からパッケージがpackagecloudで提供されるようになりました。(packagecloud)
5.1.0はどうなったの?という話ですが、ちょっと問題となるバグがあったため翌日にすぐ5.1.1を出した感じです。
今回のリリースでは4.1.4/4.1.5で変更された内容と細かい機能修正(VCL変更含む)があります。(それについては割愛してます)
VCLの変更はあるものの修正しないと動かないような変更はないのでよほどのことがない限りそのまま動作するはずです。
なお、VMODについては動かなくなるものもあるので事前に使用しているものが動くかを確認したほうが良いでしょう。
また、累積バグも修正されているのですが、よほど修正されているバグで困ってない限りは本番への適用は一旦4月中旬までは様子見たほうが良いかと思います。(何もなかったらすいません)

機能強化

varnishdのパラメータ追加(-I [cli file])
workerが起動する前に指定されたcli file読み込まれます。
このファイルはvarnishのcliコマンド(vcl.loadやvcl.useなど)が列挙されています。
これがなんの役に立つのかというと、5.0.0で追加されたvclのラベル機能を使っている人には非常に便利な機能です。
以前紹介したとおりlabel機能を使うには先にvcl.loadを利用してラベルを定義する必要がありました。
しかしvarnishdでvclを読み込む-fオプションではラベルを指定できなかったため、有効に使うには別にスクリプトを作るなど若干めんどくさかった面も否定できませんでした。
しかしこのオプションを使うことでworkerが起動する前にラベル付きでvclを読み込むことができるので非常に楽になります。


vcl.load panic /etc/varnish_panic.vcl
vcl.load siteA0 /etc/varnish_siteA.vcl
vcl.load siteB0 /etc/varnish_siteB.vcl
vcl.load siteC0 /etc/varnish_siteC.vcl
vcl.label siteA siteA0
vcl.label siteB siteB0
vcl.label siteC siteC0
vcl.load main /etc/varnish_main.vcl
vcl.use main

このようなcliファイルを作っておいて


sub vcl_recv {
    if (req.http.host ~ "asite.example.com$") {
        return(vcl(siteA));
    }
    if (req.http.host ~ "bsite.example.com$") {
        return(vcl(siteB));
    }
    if (req.http.host ~ "csite.example.com$") {
        return(vcl(siteC));
    }
    // Main site processing ...
}

このようなVCLを使うことでラベル機能を使うことが出来ます。

なお、コマンドの先頭に「-」をつけることでそのコマンドが失敗しても処理を続行することができます


起動に失敗する
vcl.load nf /etc/varnish/notfound.vcl
 
起動に失敗しない
- vcl.load nf /etc/varnish/notfound.vcl

varnishdのパラメータ追加(-x (parameter|vsl|cli|builtin))
これは何かしらの動作がというわけではなくて以下の情報が表示されるコマンドです

parameter
起動パラメータ(-p)の情報(デフォ値など)

vsl
vslのタグや出力フォーマットの説明

cli
varnishのcli(vcl.listなど)の説明を出力します

builtin
builtin.vclを出力します

HTTP/2がより使えるようになりました
5.0.0のHTTP/2は正直検証環境でも使うには辛いものだったのですが(POST投げると落ちるなど)
5.1.1では一部気をつけるポイントはあるものの検証環境で使えるぐらいには動きます。
また、HTTP/2関連は5.1.1リリース後も積極的にバグ修正が行われており、もし使いたい場合はこの記事で紹介したpkg-varnish-cacheを使って最新のコードで試すことをおすすめします。
なお、気をつけるポイントですが以下のとおりです。

  • 転送サイズ(varnishncsa %I %Oなど)などの統計がすべて0 #2238
  • bodyがあるリクエストでcontent-lengthがある場合でもTransfer-Encoding: chunkedを付与する #2247
  • クッキーの畳み込みを行わないのでVCLでクッキーの操作を行う場合に問題がある #2291 #2300

です。
統計については現時点ではどうしようもないのですが、ほかについては以下のVCLで一旦回避可能です。
もちろん修正された場合は不要となります。


sub vcl_recv{
  if(req.http.cookie){
    // temporary...
    // https://github.com/varnishcache/varnish-cache/issues/2291
    // https://github.com/varnishcache/varnish-cache/issues/2300
    std.collect(req.http.cookie);
    set req.http.cookie = regsuball(req.http.cookie,", ","; ");
  }
  if(req.proto ~ "HTTP/2"){
    if(req.http.content-length){
      // temporary...
      // https://github.com/varnishcache/varnish-cache/issues/2247
      unset req.http.content-length;
    }
  }
}

なお上記で行っているクッキーの畳み込みですが、もしESIを利用していない場合はHTTP/2に限定しても問題ありません。
他の注意点としてはPRIV_TASK/PRIV_TOPを利用しているvmodについては現時点では避けておいたほうが無難です。(HTTP/1では問題ありません)
またHTTP/2関連のパラメータとして以下が追加されています

  • h2_rx_window_increment
  • h2_rx_window_low_water

デフォルトは10MBで十分大きいので特に変更する必要ははなさそうですが、
大きなPOST/PUTを受ける場合は大きくしても良いかと思います。

即処理を終了するためのreturn(fail)が追加されました
これはどのvclアクションからも呼び出すことができます。
なおfailの後はvcl_synthがコールされますが、デフォルトでresp.statusには503がresp.reasonにはVCL failedが入っていますので、特に操作をしない場合はクライアントからは503が見えます。
なおvcl_synth内でfailを呼び出した場合は接続をアボート(即切り)します。

vcl_backend_responseでreturn(pass(DURATION))が追加されました
要はhit-for-passです。
TTLを同時に指定することができるので以前より指定しやすくなったので便利かと思います。
この辺(HFP等)わかりづらいとおもうので動きの解説記事をそのうちかきます・・

vsl queryでvxidの指定ができるようになりました
vxid(x-varnishレスポンスヘッダ)はリクエスト毎に発行されるので当然ながら事前にわかりません。
ヘルスチェックなどはvxid=0で実行されるのでそれの絞込ぐらいにしか使えないのかというとそうではなく
varnishncsaなどのlog系オプションの-dと組み合わせることで強力に使用できます。
varnishのログはメモリ上(VSM)に保存されるのですが、これはリングバッファのため古いログも多少残っています。
-dオプションは残っているログの先頭から出力するオプションのため、リクエストを行った後に取得したvxidを指定することでvarnishの挙動の確認を行うことが容易にできます。

fallback directorにstickeyオプションを追加しました


new fb = directors.fallback(sticky = true);

fallbackのdefaultの挙動では優先度の高いバックエンドがsickになった場合は当然fallbackします。
今回のstickeyオプションを指定するとこの優先度の高いバックエンドがhealthyになったときの挙動が変わります。
指定がない場合は優先度の高いバックエンドが選択されますが、指定がある場合はそのまま今繋いでるバックエンドを使用し続けます。
この動作は順繰り行われ、一番優先度の低いバックエンドがsickになった場合は再度先頭から評価されます。

起動時にvmodのバックアップを行うようにしました
これはVarnishの起動しているときにvmodの差し替えが行われて、その後の操作(reloadなど)でおかしくなることがあったので、使うvmodについてはバックアップを取るようになりました。

IPアドレス同士の比較ができるようになりました
vmod_stdにgetenvとlate_100_continueが追加されました

仕様変更

vcl_dirはvcl_pathに変更されます(起動パラメータ)
vmod_dirはvmod_pathに変更されます(起動パラメータ)
req.ttlは廃止予定です
beresp.storage_hintは廃止予定です
完全に同じものではないのですがberesp.storageで代替可能です。
レスポンスコードを1000以上でも指定できるようにしました
これはあくまでもVCL中で使うためのもので、実際にレスポンスされるときは1000以上の桁は削られます。
要はreturn(synth(1000))とかで指定しておいて、vcl_synthで処理するのに使う感じです。
DURATION型をBOOL値として使用することができるようになりました
0以下はfalseでそれ以外はtrueです
TIME型にDURATIONを加算・減算できるようになりました
REAL型にINTを加算・減算できようになりました

パラメータの追加

ban_cutoffが追加されました(起動パラメータ)
req.storageが追加されました
これはrequst bodyを保存するのに使用されます。
未指定の場合はTransientが使用されます。

バグ修正

基本的には4.1.4/4.1.5で修正されたものが大きいものだったので割愛します。


2月 102017
 

4.1系の最新版の4.1.5がリリースされました。 [changelog] [公式のリリース文]

公式でも触れられてる通りほぼバグフィックス(あとドキュメント周り)なのですが、1点パフォーマンスに影響する修正があります。
個人的に重要かなと思うのは#2106の修正です

バグ修正

workspaceが溢れた場合にpanicしていたのを修正 #1834

Basic認証でAuthorizationのフォーマットがおかしい場合varnishncsaでデコードできない問題の修正 #2148

VCLでバックエンドの比較が動いていなかったのを修正 #2168

VSMの使用状況のカウンタ(vsm_free)がおかしかったのを修正 #2188

ESIのincludeでパスが存在しない場合にpanicしたのを修正 #2197
「http://foo/」の場合は問題なかったのですが「http://foo」の場合は今までpanicしていました
その修正になります。

INT/REAL型において「-」をパースできなかったのを修正 #2167
要は-10とかを扱えるようになりました。

beresp.backend.ipが本来使用できないbackend_errorで呼び出すとpanicしたのを修正 #1865
backend_responseでのみ利用できるように修正されました

CNT_Requestでパニックしていのを修正 #2106

仕様変更

バックエンドへの接続にNagleアルゴリズムを使っていたのをやめました #2134
クライアントとの通信はもともとTCP_NODELAYだったのですがバックエンドとの通信はTCP_NODELAYを指定していませんでした。
キャッシュが出来ないオブジェクト(pass)の場合だと多少効いてくるのではと考えています。

改善

devicedetect.vclをアップデートしました(bot情報)


2月 092017
 

少し前にスロットルでサイトを守る(vmod-vsthrottle)で異常なリクエストに対してスロットルをかける方法を紹介しました。
しかしこれはあくまでリクエストレートのみで、そのリクエストがどれだけ帯域を使うかは制限しません。
例えば特定のリソースについては帯域を制限をかけたい場合や(動画のようにDL中でも再生できるのであれば、必要なビットレート+αでもいいかなとか)
ユーザの属性(課金状況など)や、はたまたリクエストが多いユーザに対しては制限をかけたい場合などいろいろあるかと思います。
今回は帯域制限を行うvmod-tcp(ドキュメント)を紹介します。

環境について

vmod-tcpでの帯域制限はtc-fqのSO_MAX_PACING_RATEを指定することによって実現しています。
これはカーネル3.13からの機能のためUbuntuであればTrusty以降が必要です、CentOSの場合はカーネルを新しくする必要があるかと思います。(7だと3.10なので)

インストール

これはvarnish-modulesの中に入ってる一つなので、インストールについては前回の記事を参照ください。

tc-fqに切り替え

先程も述べたとおりtc-fqの機能を利用しているためこれを使うようにします。
tcについてはこちらが詳しいので参照ください(よくわかるLinux帯域制限)

まず、現在のqdiscを確認します


xcir@gw01:~$ tc qdisc show dev eth0
qdisc pfifo_fast 0: root refcnt 2 bands 3 priomap  1 2 2 2 1 2 0 0 1 1 1 1 1 1 1 1

eth0のところは環境によって変更してください(制限したいインタフェース)
今はpfifo_fastを利用していることがわかります。

次にfqに変更します


xcir@gw01:~$ sudo tc qdisc add dev eth0 root handle 1: fq
xcir@gw01:~$ tc qdisc show dev eth0
qdisc fq 1: root refcnt 2 limit 10000p flow_limit 100p buckets 1024 quantum 3028 initial_quantum 15140

qdiscがfqになりました。
これでvmod-tcpによる帯域制限が利用できます。

使い方

すごい簡単です。
例えばdatファイルに対して制限をかけたいのであれば


sub vcl_recv {
  if(req.url ~"\.dat(\?.*)?$"){
    // 1000KB/s(8Mbps)
    tcp.set_socket_pace(1000);
  }
}

とするだけです。

では、実際に動作確認をしてみましょう。


xcir@gw01:~$ curl http://*****:6081/10MB.dat  > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10.0M  100 10.0M    0     0   944k      0  0:00:10  0:00:10 --:--:--  943k

xcir@gw01:~$ curl http://*****:6081/10MB.dat2  > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 10.0M  100 10.0M    0     0   260M      0 --:--:-- --:--:-- --:--:--  263M

10MBのファイルでやってみましたが、帯域制限に引っかかる方は943KiB/sなので大体8Mbpsでうまく制限されています。(10MB.dat)
対して引っかからない方では263MiB/sと制限されていないことがわかります。

注意事項

割りと簡単に使用できる帯域制限ですが注意する点がいくつかあります。

keep-alive時の制限の持続
この制限はtc-fqを利用してコネクション単位で行われます。
そのためkeep-aliveでコネクションを再利用した場合は当然のことながら制限は持続します。
なので例えば以下のように取得してみると


xcir@gw01:~$ wget http://*****:6081/10MB.dat  http://*****:6081/10MB.dat2
--2017-02-09 20:02:10--  http://*****:6081/10MB.dat
Connecting to *****:6081... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10485760 (10M) [application/x-ns-proxy-autoconfig]
Saving to: '10MB.dat'

100%[============================================================>] 10,485,760   943KB/s   in 11s

2017-02-09 20:02:20 (945 KB/s) - '10MB.dat' saved [10485760/10485760]

--2017-02-09 20:02:20--  http://*****:6081/10MB.dat2
Reusing existing connection to *****:6081.
HTTP request sent, awaiting response... 200 OK
Length: 10485760 (10M)
Saving to: '10MB.dat2'

100%[============================================================>] 10,485,760   942KB/s   in 11s

2017-02-09 20:02:31 (944 KB/s) - '10MB.dat2' saved [10485760/10485760]

FINISHED --2017-02-09 20:02:31--
Total wall clock time: 22s
Downloaded: 2 files, 20M in 22s (945 KB/s)
xcir@gw01:~$

制限がかからないはずの10MB.dat2についても制限がかかっているのがわかります。

なので、例えば先程の場合であればdatファイルをダウンロードした後(8Mbps)にコネクションを再利用して画像などのリソースをダウンロードする場合は8Mbpsとなります。
なにかリセットする方法がないかなと0を指定しても特に解除されなかったため、vcl_recvの先頭で十分な大きさの指定をしておくと良いと思います。


sub vcl_recv {
//8Gbps
tcp.set_socket_pace(1000000);
  if(req.url ~"\.dat(\?.*)?$"){
    // 1000KB/s(8Mbps)
    tcp.set_socket_pace(1000);
  }
}

このようにして試してみると


xcir@gw01:~$ wget http://*****:6081/10MB.dat  http://*****:6081/10MB.dat2
--2017-02-09 20:03:40--  http://*****:6081/10MB.dat
Connecting to *****:6081... connected.
HTTP request sent, awaiting response... 200 OK
Length: 10485760 (10M) [application/x-ns-proxy-autoconfig]
Saving to: '10MB.dat'

100%[============================================================>] 10,485,760   943KB/s   in 11s

2017-02-09 20:03:51 (945 KB/s) - '10MB.dat' saved [10485760/10485760]

--2017-02-09 20:03:51--  http://*****:6081/10MB.dat2
Reusing existing connection to *****:6081.
HTTP request sent, awaiting response... 200 OK
Length: 10485760 (10M)
Saving to: '10MB.dat2'

100%[============================================================>] 10,485,760  47.7MB/s   in 0.2s

2017-02-09 20:03:51 (47.7 MB/s) - '10MB.dat2' saved [10485760/10485760]

FINISHED --2017-02-09 20:03:51--
Total wall clock time: 11s
Downloaded: 2 files, 20M in 11s (1.81 MB/s)

と、意図したどおりに動作します

TLS終端を別MWで行いlocal接続しているケースに効かない
Varnishはhttpsを喋れないのでTLS終端をnginxやhaproxyやhitchなどで行いローカルで接続しているケースもあると思いますが
その場合はloインタフェースもtc-fqを適用する必要があります。

http/2利用時
http/2は複数のストリームが1コネクションに入っています。
そのため特定のリソース(=特定のストリーム)のDL時のみを帯域制限をかけたい場合には使用できません。
この場合全体での制限になります。
もちろん、特定の行動をしたクライアントの帯域を絞りたいという用途には利用できます。


12月 042016
 

VarnishCacheはOSSですがPHKとVarnishSoftwareなどが主となって行っています。
個人や組織は当然ながら資金なしで活動できるわけではなく、VarnishSoftwareの場合はVarnishに多数の機能が追加されているVarnishPlusをサブスクリプション販売したいたりします。
ではPHKはどんな感じで資金を得ているかというとVarnish Moral License(VML)というので資金を得ています。
VMLで資金を得てその範囲でPHKが様々な新機能や改修を行っていたりするのですが、少し前のVarnish5の開発で資金が足りなくなってきました。
そのためVarnishの開発時間を取るためにVML購入を求める記事が公式にあがっていましたが
(Send us (more) money!)
今回、自分が実際にVMLを500EURほど購入してみたので、どんな感じのフローでやったのかなどを紹介します。

そもそもVMLとは

先程も述べたとおりPHKがVarnish関連の活動をするための資金です。
VMLのページに書いてあるとおりなのですが

Software development may be open, and the result shared with an Open Source Software licence, but the actual hours of programming are not gratis.
Just like everybody else, I need money for mortgage, kids and food, money I make by doing things with computers, for people who are willing to pay for that.
One of the things I do for money, is develop Varnish, and the Varnish Moral License is the vehicle I invented for the paperwork.

(意訳)ソフトウェアの開発はオープンで、その成果物はOSSとして共有されますが、その開発に費やされる時間は無償ではありません。皆さんと同じように、私は住宅ローンを、子供を養う、食べていくためにコンピュータを使って稼ぐ必要があります。私が稼ぐ一つの手段がVarnishの開発で、VMLはそのために開発した仕組みです。

ちなみに、現在VMLを継続的に購入しているユーザは

  • Fastly
  • VarnishSoftware
  • UPLEX

の3社です。

ちなにみVMLを購入することで何かしらのサービスやサポートが受けられたりするわけではありません。
(当然、欲しい機能をリクエストして優先されるわけでもありません)
支払った金額の分だけPHKがVarnishに時間を費やすことで開発が前に進む感じです。
VMLのFAQについてはここにあるのでぜひ目を通してみてください。

2019/05/02追記

現在VMLを€240以上購入すると、1年の間にセキュリティインシデントがあった場合は早期に共有されるようです

実際にVMLを購入したときの手順

購入希望のメールを送る
まずはPHK宛にメールを送ります。
メアドはここにあるものです。

含まれる必要がある内容は

  • 購入するラインセンス額(How much do you want to pay for your license ?)
  • それは定期購入(期ごと、月ごと)か1回のみか(Do you want to pay it monthly or quarterly ? (or onetime ?))
  • Webページに記載される名前(What name should appear on the web-page ?)
  • 請求書に記載される名前(What name should appear on the invoice ?)

です。
自分が実際に送ったメールはこんな感じです。
vml1
ついでにこの記事を書きたかったので書いてもいいかを聞いています。

ちなみに今回500EUR(6万円ぐらい)を送金しています。もっと少なくてもいいのでしょうか?
これは海外送金の難しいところで自分はそこまで詳しくないのですが、
海外送金の場合だと受け取るのにもお金が必要で、FAQにもあるのですが100EUR以下の場合は手数料のほうがかかってしまうらしいです。
また、当然ながらPHK側の事務コストが発生しますのでそのあたりを勘案して考えると良いかなと思っています。
(メールで「私が避けたいのは5ドルの請求書を200枚も書くような状態に陥ることだ」と言ってました)
もし、VMLは煩雑なので他の方法がないかといえばWishlistもあります。
実際、自分はVMLの海外送金がめんどくさくて何度かリリースがあったタイミングでWishlistを消化してました。
なぜ今回VMLを購入したかというと公式サイトにVMLについて書いてあったのと、Wishlistに買えるものがなかったからです。

請求書が来る
請求書はPDFで送られてきます。(自分の場合は1週間ぐらいできました)
vml2
マスクしてる箇所は住所とか電話番号が書いてあった感じです(一応公開してOKって確認とりました)

海外送金をする
最初なんでPaypalが使えないんだろうと思ったんですが
以前に資金集めを行った際に使っていろいろあったようです。
ということで銀行で海外送金をする必要があります。
海外送金のめんどくさいところが、500EURを送ろうとしても実際に500EURが相手に渡るかわからないところです。
中継銀行で手数料が引かれたりすることもあります。
海外送金できる銀行はたくさんあるのですが(ゆうちょでもできます)
中継手数料などを先に支払ってしまえる銀行を探したところ楽天や三井住友などがあったので今回は三井住友銀行を使いました。
vml3
これ書いた後に大変だったのが、銀行側で「æ」に対応するキーがなくてなんて入力していいかがわからなかったことですw
aeで書いて着金したのでこれで大丈夫みたいです。

たしか翌週に三井住友から明細書が自宅に送られてきました。
vml4

これで送金は完了です。

で、翌月ぐらいにVMLの明細のところに名前がのります。
vml5

まとめ

Varnish5がリリースされてhttp2に実験的なサポートをするなどしましたが、まだまだバギーで改善が必要です。
今回少額ながらVMLを購入しましたが少しでもその改善に役に立てば嬉しいですし、この記事を公開することでVarnishを使っている方でVMLの購入を検討してくれると嬉しいなと思います。


12月 022016
 

4.1系の最新版の4.1.4がリリースされました。 [changelog] [公式のリリース文]
主にバグ修正とドキュメントの改善ですが
1件すごくタイムリーなバグ修正が存在します。
また、今回のリリースで4.0.xがEOLになりました。

バグ修正

バックエンドの現在の接続数のカウンタが機能していないのを修正 #2011

ラウンドロビンDirector利用時にクラッシュすることがあるのを修正 #2024

フェッチ時にワークスペース・ストレージ確保失敗するとリークする可能性があったのを修正しました

return(pipe)時にstd.cache_req_bodyが機能しないのを修正 #1881

vmod_named利用時にVBE_Deleteでpanicすることがあるのを修正しました #2008
コードの修正を見た感じnamedに限らずに動的にバックエンド定義をUpdateしていくようなDirectorの場合に問題が起きそうです。

エラーなどで起動できなかった場合にvsmファイルが残っていたのを修正しました #2115

keepalive時に複数のrangeリクエストが来た場合に先頭リクエスト以外をしばらくブロックすることがあるのを修正しました #2035

バックエンド選択時に稀にpanicするのを修正しました #2027

時刻が逆行(STEP)した場合に子プロセスが再起動する場合があるのを修正しました #1874
うるう秒もありますのでこのあたり注意しておいたほうが良いと思います。
条件としてはセッションがクローズ(close)されるタイミングの時刻がセッション開始時刻(open)が早くなっていた場合です。
Varnishのこの時間の精度はナノ(clock_gettime/CLOCK_REALTIME)もしくはマイクロ秒(gettimeofday)なので
うるう秒で23:59:58->59->59->00のように59を繰り返す場合(STEP)でリクエスト自体を1秒未満で処理していると引っかかる可能性があります。
そのため、今回のうるう秒でSTEP動作をする可能性がある場合は強くアップデートを勧めます。
なお5.0.0も影響を受けます。今のところ5.0.1がリリースされる気配はないのでSLEWで動かすか独自で現時点のmasterのものをビルドするかをおすすめします。(4.0.xは影響なさそうです)
また、この問題の解決のためにclock_stepといパラメータが追加されています。

機能強化

varnishhistの表示にy軸が追加されました
5.0.0のhistと同じ表示です。

仕様変更・追加

varnishtestで外部のコマンドを実行するfeature cmdが追加されました。
すでにあるshellコマンドとの違いですが、shellの場合はその実行結果でテストが成功・失敗しますが
feature cmdの場合はテスト自体が実行されるかされないかです。
混在環境(OSやCPU)で特定環境のみのテストを行う際に便利に使えると思います。

varnishtestのresp.msgはresp.reasonに変更されました

clock_stepが追加されました
時刻同期で一気に時刻が変更(STEP)された場合の許容秒数です。
デフォルトは1秒です。

thread_pool_reserveが追加されました
重要なタスクのために予約されるスレッド数です。
例えば、クライアントの処理でスレッドを使い尽くした場合でもreserveされているスレッドがあればバックエンドの問い合わせが可能です。
この値は引き上げるとクライアント処理で使われるスレッド数が少なくなるため注意する必要があります。
あくまで一気にリクエストが来てスレッドが足りなくなった場合に発動するものなので、普段から適切なスレッド数を指定していればそこまで問題無いと思います。
デフォルトは0(auto)で、thread_pool_minの5%が自動的にセットされます。

パッケージ構成が変更されました
5.0の構成とおなじになりました。(varnish = varnish + libvarnishapi + varnish-doc)
そのためそのままapt-get installで更新しようとすると失敗します。
一度4.1.3までのバージョンをremoveしてアップデートするのをおすすめします

その他変更

ドキュメントの改善やRaceコンディションで起きる幾つかのバグが修正されています。


7月 132016
 

Varnish4.1.3がリリースされました。
バグフィックスが主でアップデートを強く進めますが、他にも結構使える新機能が増えています。

ダウンロードはこちら
changes

新機能・変更

varnishncsaにバックエンドに問い合わせにいったものだけを表示するオプションが追加されました(-b)
今までは幾つか絞込の指定をしないと取れなかったのですが-bだけで済むので便利です
また同時にクライアントで絞り込んで表示するオプション(-c)も追加されています。(デフォルト動作)
ちなみに-b -cを同時に指定することも出来ます。

VSMを開放する際にどれだけ待機するかのパラメータが追加されました(vsm_free_cooldown)
今までは60秒でハードコードされていました。デフォルト値も60秒です。
通常の使い方ではいじることはないと思いますが、かなり激しいログの書き込みをするとかの環境だといじる機会はあるかもしれないです。

varnishlogの出力でバックエンドのトランザクションが開始する際にBackendStartが入るようになりました
クライアントのReqStartと対になるものです。

varnishncsaの-Fで指定できるものが増えました
3つ増えました。
 Varnish:side
 先ほど紹介した-b -cオプションに伴って増えたものです。
 バックエンドで絞込をしている場合はbを、クライアントからの表示の場合はcを出力します。
 -b -cを両方指定している場合に使うとどちらのログなのかがわかって良いと思います。
 Varnish:vxid
 vxidを出力します
 VSL:tag VSL:tag[field]
 指定したタグ(TimeStampなど)を出力します。
 基本vsl-queryと同じ指定ですがヘッダ指定は出来ません(VSL:ReqHeader:User-Agentみたいなのは出来ない)
 これできるといいなーと思うのでp-r書こうかな・・
 ちなみに複数引っかかる場合は最初のを出力します。
 例えばVSL:TimeStampを指定した場合は毎回Startのタイムスタンプが表示されます

TCP Fast Openをサポートしました
デフォルトはoffです(tcp_fastopen)

varnishtestに新しい同期用の命令を追加しました(barriers)
semaより使いやすいです

varnishstatで12桁以上の数値を出力する場合は丸めるようにしました#1855
CURRENTの表示でK/M/G/Tのように単位がつけられないカウンタは” %12ju”だったのですが12桁を超える場合は1000で割って” %9ju…”という表示になります。
コードを見た限りではxml/jsonで出力するときには影響しないのでそこまで気にすることはないかなと思います。

バグ修正

今回はかなりバグ修正が多いので幾つかピックアップして紹介します。
特にESI周りの修正が多いのでESIを使っている場合はアップデートすると良いと思います。

varnishncsaで-Lオプションが受け付けられないようになってたのを修正しました#1994

たまにAgeとAccept-Rangesヘッダが複数レスポンスされることがあるのを修正しました#1955

同名のVCLでvarnishをstop->startを繰り返すとその後segfaultを繰り返す事があったのを修正しました。#1933
dlopenのリファレンスカウンタが信用ならなかったみたいです。
vcl名は変わらないのですが、コンパイルしたvgc.soのパスに現在時刻(ナノ秒)が付与されるようになりました。
バッドアイデアとメッセージにあるので割と苦悩した感じがあります。

vcl_init/finiでstd.log/std.syslogを利用するとクラッシュするのを修正しました#1924

VSMのサイズが小さくてオーバーラン検出に問題が合ったのを修正しました#1873
varnishncsa等でオーバーランした際にもクラッシュしなくなりますが
オーバーランしたらvsmサイズを増やしたほうが良いでしょう。
それでも困るようであれば今回追加されたcooldownの調整も考えると良いかも

-Cオプション利用時にテンポラリで使用したディレクトリを消していなかったのを消すようにしました#1869

POSTリクエストをpipeで繋いだ場合に1分待たされることがあるのを修正しました#1806
4.1からはPOSTリクエストのデフォルトの動作がpassになっているので通常の場合は問題ないのですが
以前からの設定を使いまわしてる人などは割りとハマるかもしれないです。

バックエンドの接続数を示すカウンタを復活させました#1725
バックエンド周りのコード修正した際に意図せず消えたカウンタを復活させました。
確かに消えてました・・気づかなかった・・

次は5.0.0かなー
楽しみですね


3月 072016
 

Varnish4.1.2がリリースされました。
バグフィックスが主ですが、一部新機能があります。

ダウンロードはこちら
changes

また2016-03-09 12:00 CET(日本時間 同日20時)からリポジトリの場所が変更になります。
これは去年アナウンスされていたVarnish Cache project autumn cleaningの一環になります。
また、まだドキュメント側は更新されていませんがバグ報告についてもgithubに移行するはずです。

機能追加/改善

REAL型同士で算術演算子を使えるようになりました
4.1.1まではREAL型同士は+以外は使えなかったのですが新たに-*/がサポートされるようになりました。(1.1 – 0.9とかが出来るように)

absoluteURIでhttpsからはじまる場合でもHostをパース出来るようになりました
言葉にするより表のほうがわかりやすいと思いましたので動作パタンを表にしました。

  http://example.com/foo https://example.com/foo
Version req.http.host req.url req.http.host req.url
~4.1.1 example.com /foo https://example.com/foo
4.1.2~(with feature +https_scheme) example.com /foo example.com /foo

PROXYプロトコルに4.1で対応したしといった感じかと思います。
なお、標準ではoffになっているのでfeature +https_schemeを指定する必要があります。

VMODでACLが扱えるようになりました
vmodtool.pyを改善して4.0/4.1でソースツリーを共有出来るようにしました
おもにVMOD作成者向け

vmodtool.pyを改善して1つのディレクトリから複数のvmodを作成コンパイル出来るようにしました
varnish-modulesというのが少し前に公開された(Varnish謹製のVMOD集)のですが、これのための対応といった感じです

バグ修正(一部抜粋)

Content-LengthがないHTTP/1.0かつPOST/PUTした場合すぐ400を返すように変更(#1843)
今まではchunkedとして扱ってしまって結果としてtimeoutを待ってましたが400をすぐ返すように変更しました。

フェッチ時(VFP_Push)にworkspaceがオーバーフローした場合panicしていたのをFetchErrorに変更しました(#1739)
panicするほどのエラーではないということで変更です。

hit-for-pass利用時にbodyが空っぽになるケースがあったのを修正(#1858)
本来不要なIMSの評価を行っていたため結果としてbodyが空っぽになるケースがあったのでhit-for-pass時のIMSの評価を辞めました。

ESI利用時にメモリリークするケースがあったのを修正(#1860)
これはAddressSanitizer(ASAN)で検出したのです。(他にも#1852を検出しています)
ASANについては以下を見てみると面白いと思います
CAN WE RUN C CODE AND BE SAFE?

ban-listを回収(ban-lurker)してる際にpanicするケースがあるのを修正しました(#1863/#1864)


2月 032016
 

Varnish4.1.1がリリースされました。
ドキュメントの修正や、バグフィックスが主ですが幾つかの仕様変更があります。
4.1.0を利用している場合はアップデートをおすすめします。

ダウンロードはこちら
changes

機能追加

varnishncsaに-fオプションが追加されました
これは単純に-Fで指定するフォーマットをファイルから読み込みができるというだけです。
エスケープ等が面倒な時はよいかもしれないです。

仕様変更

varnishncsaはデーモンで動作する際に-wオプションが必須になりました
-wはファイルに出力するオプションで、通常デーモンで動作させる場合は指定しているものなので特に影響はないかと思います。

If-None-Match(INM)とIf-Modified-Since(IMS)リクエストが同時に来た場合IMSを無視します
この動作自体はRFC7232の3.3に記述されている通りです
(A recipient MUST ignore If-Modified-Since if the request contains an If-None-Match header field)

ステータスコードが1xx, 204, 304の場合はContent-Lengthヘッダをレスポンスしません
これらのステータスコードはbodyを含みませんので不要です。

VCLをネストしてincludeする際のカレントディレクトリをそれぞれのVCLのディレクトリに変更しました
いまいち一文で書くとわかりづらいのですが用はこういうことです。


/etc/varnish/default.vcl
/etc/varnish/common/base.vcl
/etc/varnish/common/acl/internal.vcl
/etc/varnish/common/acl/admin.vcl

例えばVCLをこのように配置していて相対パスでincludeする場合


~4.1.0
■/etc/varnish/default.vcl
vcl 4.0;
include "./common/base.vcl";

■/etc/varnish/common/base.vcl
vcl 4.0;
include "./common/acl/internal.vcl";
include "./common/acl/admin.vcl";

4.1.0までは基点となる/etc/varnish/を基準とした相対パスで書く必要がありましたが、
4.1.1からは


4.1.1~
■/etc/varnish/default.vcl
vcl 4.0;
include "./common/base.vcl";

■/etc/varnish/common/base.vcl
vcl 4.0;
include "./acl/internal.vcl";
include "./acl/admin.vcl";

このようにincludeが記述されたVCLのディレクトリを基準として読み込みます。
割と便利だと思います

hit-for-passもgrace動作するようになりました(#1818)

vcl_dir, vmod_dirにコロン区切りで複数のディレクトリを指定できます

varnishreplayが削除されました
少し前からコンパイルされないようになっていたのですがコード自体も削除されました。

バグ修正(一部抜粋)

大きなファイルを扱う際に遅くなっていたのを修正(#1798)

IPv6アドレスのパースに失敗するのを修正(#1801)

PROXYプロトコルを利用した際にvarnishlogが正しく表示されないケースがあったのを修正しました(#1804)
Proxyプロトコルのvxidが0になっていてその影響で-g request, sessionがうまく動きませんでした。

INMリクエストでETagを比較する際に弱い比較関数を使用するようにしました(#1816)
RFC7232に準拠した形です。

vsl-queryでフィールドをfloatsで評価しようとした場合に評価できないのを修正(#1845)
4.1.0からのデグレですが、具体的には”timestamp:resp[2] > 1.”のような絞り込みができなくなってました。


12月 052015
 

この記事はVarnish Cache Advent Calendar 2015の4日目の記事になります。

VCLには様々な変数の型がありまして、それぞれの型の間では暗黙的に変換されるものと、vmod_stdを使用して明示的に変換するものがあります。
型が結構多いのでいまいち何を使うか忘れることが多いので図にしてみました。
types
なお、ここでは特に変換にかかわらない型については取り上げていません(BLOB,ENUM,HTTP,PRIV_CALL,PRIV_VCL,PRIV_TASK,PRIV_TOP,PROBE,VOID)

ちなみに各型から暗黙的にSTRINGへ変換すると以下のようになります。

変換例
BYTES 2.000
DURATION 2.000
REAL 2.000
BOOL false
BACKEND default
INT 1
IP 192.168.1.1
TIME Fri, 04 Dec 2015 18:31:12 GMT
HEADER example.net

また、STRING_LISTですが基本的にはSTRINGと特に違いはないのですが、
これを引数として受け付ける関数の場合は型変換を意識しないとハマります。
例えばstd.logというログを出力する関数があるのですが、これは引数がSTRING_LISTです。
それを意識して以下のようなVCLを書くとエラーになります。


std.log(std.duration("10w",0s));


Command failed with error code 106
Message from VCC-compiler:
Wrong argument type.  Expected STRING_LIST.  Got DURATION.
('input' Line 31 Pos 31)
std.log(std.duration("10w",0s));
------------------------------#-
('input' Line 31 Pos 1) -- ('input' Line 31 Pos 30)
std.log(std.duration("10w",0s));
##############################--
Running VCC-compiler failed, exited with 2

これはdurationから一気にSTRING_LISTに暗黙的に変換できないからです。
そこでどうやるかというと、一度STRINGを経由させてあげればよいので


std.log("" + std.duration("10w",0s));

このように空文字を結合すると良いです。

まとめ
変数がどのように型変換が出きるかを知っておくと、その型では出来ない演算を変換した先でやって戻すみたいなことが出来ます。
覚えておくと結構便利なので、頭の片隅に置いておくと良いかなと思います。


12月 022015
 

この記事はセカイエ Advent Calendar 2015Varnish Cache Advent Calendar 2015の2日目の記事になります。
かなり前の話(8月)になるのですがリノコという定額リフォームサービスのサイトがTV東京のワールドビジネスサテライト(以下WBS)に取り上げられました
ありがたいことにたっぷり取り上げていただきました。その際に少しだけVarnishを使って負荷対策をお手伝いしたのでその時のことを書きます。
(なおここでとった対策は緊急ということで外しています。)

TV放映される上で負荷対策として検討したこと

  1. スケールアップ・アウト
  2. トップページ及びそこから回遊されるページの静的化
  3. Varnish導入

動き的には1を検討してみてその結果たりなさそうという判断を行い2,3を並列で行った感じです。

スケールアウト
リノコではクラウドを利用しているわけで当然スケールアウトを考えるわけですが
残念がらコード側があまりスケールするような仕組みになっておらず、例えば10倍サーバを投入してもスケールアップ・アウト出来ない箇所がボトルネックになって無駄になってしまう状態でした。
そのため最低限のスケールアップ・アウトを行いました 。

トップページ及びそこから回遊されるページの静的化
現地メンバーにお願いしましてコードを修正することでページの静的化することで、負荷に耐えるように修正を加えようとしました。
このアプローチ自体は間違っているとは考えていませんが残念がら切り戻しています。
単純にバグってしまったということです。敗因は明らかで単純に時間がなかったということにつきます。
今回のTV放送を知ったのが放映前日で、この作業をはじめたのが放映6時間ぐらい前だったからです。(そして切り戻し判断は放映2時間ぐらい前です)

Varnish導入
リノコのサイトでは幸いな事にキャッシュを行うことができる・出来ないの判断が比較的分かりやすかったため、試しに設定を書いてみて投入してみました。
この試みは割とうまく行ったためそのままTV放送を迎えました。

結果について
まずはどの程度のリクエストが来たかですが
image2015-11-29 16-43-13
割とビビるリクエストが着ているのがわかります。
でサイトが落ちたかどうかということなのですが半分落ちました。
この半分というのはVarnishでキャッシュが可能でキャッシュが出来たページについては特に問題なくレスポンスが出来て
キャッシュが不可能なページやキャッシュは可能だが深い階層で未キャッシュのページは落ちた感じです。
負荷対策を行う上で重要なのは、かけることが出きるコストを正確に把握し、何処の優先度を上げて何処を下げるかだと思っています。
特に今回のケースでは対策に費やされる時間がほぼなかったため、最小の対策で最大の成果を得る必要がありました。
今回はTV放映時にサイトを全部落とさない、特にLPとそこから回遊しそうなページについて落とさないを目標としました。
そういう意味では今回の対策はうまく行ったと考えています。

そもそもなぜVarnishを使ったか
どうせお前がVarnish好きだからじゃないかという指摘もあるかもしれませんが
今回のケースではVarnishを使う以外の選択肢はありませんでした。
もう少し時間があれば他の手段も取れましたがその場合でも良い選択肢だと確信しています。
『幸いな事にキャッシュを行うことができる・出来ないの判断が比較的分かりやすかった』
と書きましたがこのルールは以下でした

  • 特定のパス以下のURLはキャッシュ不可
  • クッキー中に特定キーが入っていた場合はキャッシュ不可
  • 同一URLでUAによってコンテンツの出し分けを行っている(PC/スマホ)
  • etc

例えば1URLで最大どの程度のパタンがあるかというと

  • キャッシュ可能+PC
  • キャッシュ可能+SP
  • キャッシュ不可+PC
  • キャッシュ不可+SP

と4パタンがありました。
まさにVarnishの設定言語であるVCLの得意とすることで、設定は47行でした。(実質コードですが)
しかもこの対策を行う上でサイト側のコードは修正しておりません。
このような場合において最低限の対策で効果を得るにはVarnishは最適だと考えています。

まとめ(負荷対策の重要性)
メディアに取り上げられるというのはいわばボーナスステージだと僕は考えています。
しかし、見に来ていただいた方が実際に興味を覚えてもらうためにはまずサイトを見れる状態を作らなければなりません。
普通に考えて初めてサイトを見に行って重くて見れなかった、そもそも見れなかったとかであれば、すぐに記憶から薄れ再訪することはないでしょう。
そのためサイトをなるだけ見れる状態にするのを考えるべきでしょう。

また、負荷のかかり方も様々です。

  • 事前にわかるかどうか
    • 事前連絡がある
    • 事前連絡がない(予測不能)
    • イベントなどでそもそもわかる(エイプリルフールやセール等)
  • 負荷の上がり方
    • 一瞬で上がってその後落ち着く(TV)
    • 一気に上がりつつその後もじわじわ上がる(ネットメディアなど)

どんなパタンがあるだろうとさくっと書いてみましたが(サイトの特性によってここは変わると思います)それぞれの組み合わせでどのような対策を行うか考えてみるのも良いと思います。
例えば事前連絡があるのであれば、インスタンスをもりもり多めにあげて(AWSであれば)ELBの暖気申請をして・・・みたいな対策も打てます。
逆に事前連絡がないのであれば、オートスケールするまでの時間までを如何に稼ぐかという話になってくるかもしれません。
更に一瞬で上がっていつ起こるか予測不能であればその場合でもどのコンポーネントを落とさないようにするかなどの事前の設計・対策が重要でしょう。
もちろん、どのパタンにおいてもスケールするようにコード修正するとかクラウドの機能を使う/業者の選定も大事です。
また、どのパタンでもキャッシュ可能なコンテンツをキャッシュすることは有効な手段の一つだと思います(Varnishでもなんでもいいですが)