varnishでbackendのapacheにPOSTしているときにたまに(1/1000ぐらい)503 Service Unavailable になる現象はpassをpipeに変えたら出なくなった

これも同じような感じ?

backendの設定とbackendに投げる設定のvclはこんな感じ(抜粋)

  • backend
probe healthcheck {
  .url       = "/index.html";
  .interval  = 30s;
  .timeout   = 10s;
  .threshold = 3;
  .window    = 3;
  .expected_response = 200;
}
	
backend apache1 {
  .host = "192.168.0.1";
  .port = "80";
  .probe = healthcheck;
  .connect_timeout       = 60s;
  .first_byte_timeout    = 60s;
  .between_bytes_timeout = 60s;
}	

backend apache2 {
  .host = "192.168.0.2";
  .port = "80";
  .probe = healthcheck;
  .connect_timeout       = 60s;
  .first_byte_timeout    = 60s;
  .between_bytes_timeout = 60s;
}	
		
director apache fallback {
  { .backend = apache1; }
  { .backend = apache2; }
}
sub vcl_recv {
  (中略)
  if (req.url ~ "^/(foo|bar)") {
    set req.backend = apache;
    return (pass);
  }
	
  return (lookup);
}


で、このときに携帯からapacheへPOSTするときに1/1000 ぐらいの頻度で503になってた。そのときのvarnishlog を見ていると以下のようなものが流れている。varnishlog にはbackend write error と出ているが、backendのapacheのログにはerrorらしきものは見当たらない。

66 Hash         c varnish.example.com
66 VCL_return   c hash
66 VCL_call     c pass pass
66 Backend      c 25 apache apache1
66 FetchError   c Resource temporarily unavailable
66 FetchError   c backend write error: 11 (Resource temporarily unavailable)
66 VCL_call     c error restart
66 VCL_call     c recv pass
66 VCL_call     c error deliver
66 VCL_call     c deliver deliver
66 TxProtocol   c HTTP/1.1
66 TxStatus     c 503
66 TxResponse   c Service Unavailable
66 TxHeader     c Server: Varnish
66 TxHeader     c Content-Type: text/html; charset=utf-8
66 TxHeader     c Retry-After: 5
66 TxHeader     c Content-Length: 366
66 TxHeader     c Accept-Ranges: bytes
66 TxHeader     c Date: Tue, 28 May 2013 04:38:12 GMT
66 TxHeader     c X-Varnish: 1888567253 	

vcl中のpass を pipe に変えてみる

ここに書いてあるようにpassをpipeに変えてみたら、503エラーが出なくなった。

passとpipeの違い

xcirさんのvarnish cache 入門からの引用

pipe
  クライアントとバックエンド間のコネクションが閉じられるまで、継続的に
  スルーします。Varnish は内容に対する操作は行いませんし、キャッシュも
  行いません。単純に右から左へ通信を中継するだけです。

pass
  Varnish はキャッシュしません。しかし、返却時にレスポンスヘッダに追加
  で項目を加えるなどの操作は可能です。

curl などで見てみるとたしかにpassの場合はvarnishのヘッダが追加されている。

  • pass の場合
$ curl -I http://varnish.example.com/foo/
HTTP/1.1 200 OK
Server: Apache
Content-Type: text/html
Accept-Ranges: bytes
Date: Tue, 28 May 2013 14:50:04 GMT
X-Varnish: 1889133345
Age: 0
Via: 1.1 varnish
Connection: keep-alive	
  • pipe の場合
$ curl -I http://varnish.example.com/foo/
HTTP/1.1 200 OK
Date: Tue, 28 May 2013 14:51:56 GMT
Server: Apache
Connection: close
Content-Type: text/html

追記

pipe を使うと、そのリクエストはvarnishncsa ログに記録されなくなっていることに気づいた。

tcpのコネクションを丸投げしてるだけでvarnishは何もしていないから?
というわけでログを残す必要がある場合はやっぱりpassを使わないといけない。