[Varnish] #1696: Varnish leaves connections in CLOSE_WAIT

Varnish varnish-bugs at varnish-cache.org
Mon Mar 30 12:20:22 CEST 2015


#1696: Varnish leaves connections in CLOSE_WAIT
----------------------+--------------------
 Reporter:  rwimmer   |       Owner:
     Type:  defect    |      Status:  new
 Priority:  high      |   Milestone:
Component:  build     |     Version:  3.0.5
 Severity:  critical  |  Resolution:
 Keywords:            |
----------------------+--------------------

Comment (by rwimmer):

 We were able to nail the problem further down but for us it's a little bit
 wired because it's exactly one URI causing the problem and it looks like
 this: /foo/bar/suggest/heroTeaser/

 And ONLY this syntax! "/foo/bar/suggest/heroTeaser" (without / at the end)
 and "/foo/bar/suggest/heroTeaser/?some_query_string=value" works as
 expected. The cause seems to be in vcl_fetch. The original code looks like
 this:

 {{{
 ...
     if (beresp.http.Content-Type ~ "text/html" || beresp.http.Content-Type
 ~ "text/xml" || beresp.http.Content-Type ~ "application/json") {
         if ((beresp.http.Set-Cookie ~ "NO_CACHE=") || (beresp.ttl < 1s)) {
             set beresp.ttl = 0s;
             return (hit_for_pass);
         }
 ...
 }}}

 With this VCL code we see connections in CLOSE_WAIT steadily growing (ok
 we now know that this code isn't perfect but it shouldn't matter). If we
 change the code above to

 {{{
 ...
     if (beresp.http.Content-Type ~ "text/html" || beresp.http.Content-Type
 ~ "text/xml" || beresp.http.Content-Type ~ "application/json") {
         if ((beresp.http.Set-Cookie ~ "NO_CACHE=") || (beresp.ttl < 1s)) {
             set beresp.ttl = 0s;
             if (req.url ~ "^/foo/bar/suggest/heroTeaser/$") {
                 return (deliver);
             }
             return (hit_for_pass);
         }
 ...
 }}}

 everything is ok. No further growing in CLOSE_WAIT connections! We looked
 at the Varnish flow graph (https://www.varnish-
 cache.org/trac/attachment/wiki/VCLExampleDefault/varnish_flow_3_0.png)
 what part could case this behavior and finally discovered that we need to
 add some code to vcl_miss to prevent vcl_fetch called next for this URI.
 vcl_pass should be called instead. So we added the following VCL code:

 {{{
 sub vcl_miss {
    if (req.url ~ "^/foo/bar/suggest/heroTeaser/$") {
       return (pass);
    }
 }
 }}}

 Additionally we switched back to the original code in vcl_fetch mentioned
 above:

 {{{
 ...
     if (beresp.http.Content-Type ~ "text/html" || beresp.http.Content-Type
 ~ "text/xml" || beresp.http.Content-Type ~ "application/json") {
         if ((beresp.http.Set-Cookie ~ "NO_CACHE=") || (beresp.ttl < 1s)) {
             set beresp.ttl = 0s;
             return (hit_for_pass);
         }
 ...
 }}}

 If you look at the Varnish flow graph the main difference is that after
 vcl_pass an anon object is created which is completely skipped if
 vcl_fetch is called after vcl_miss. So adding the vcl_miss code we changed
 the execution path and that worked. Without vcl_miss and the "if" clause
 in vcl_miss a simple "curl
 http://somdomain.tld/foo/bar/suggest/heroTeaser/" caused a timeout after 5
 minutes (tcp timeout) and no request to the backend. "curl
 http://domain.tld/foo/bar/suggest/heroTeaser" and "curl
 http://domain.tld/foo/bar/suggest/heroTeaser/?some_query_string=value"
 returned immediately.

 It shouldn't matter how wrong the VCL code is in this case. At least an
 error should occur and not tens of thousands of connectsion in CLOSE_WAIT.
 We suspect that it has something to do with "hit_for_pass" and the anon
 object that is only created after vcl_pass was called but not if vcl_miss
 was called and vcl_fetch is executed next.

-- 
Ticket URL: <https://www.varnish-cache.org/trac/ticket/1696#comment:2>
Varnish <https://varnish-cache.org/>
The Varnish HTTP Accelerator



More information about the varnish-bugs mailing list