How to compare 'bereq.backend' and 'req.backend_hint' against a director/backend in Varnish 4.1

Plöger, Ronald ronald.ploeger at gmx.de
Thu Dec 15 09:10:01 CET 2016


We are in upgrading from Varnish 3 to Varnish 4.1 and we have 
experienced a problem when comparing 'bereq.backend' or 
'req.backend_hint' to a director or a backend.

We created Varnish Test Cases to demonstrate this behavior.

In Varnish 3 this tests runs successfully:

------------------------------------------------------------------------------------------------------
varnishtest "Test backends and directors"

server s1 {
   rxreq
   txresp -status 200
} -start


varnish v1 -vcl {
   backend b_1 {
     .host = "${s1_addr}";
     .port = "${s1_port}";
   }

   director d1 round-robin {
     { .backend = b_1; }
   }

   sub vcl_recv {
     set req.backend = d1;
   }

   sub vcl_fetch {
     if ( req.backend == d1 ) {
       set beresp.http.X-Backend-Fetch = "d1";
     }
   }

   sub vcl_deliver {
     if ( req.backend == d1 ) {
       set resp.http.X-Backend-Deliver = "d1";
     }
   }

} -start

client c1 {
   txreq
   rxresp
   expect resp.status == 200
   expect resp.http.X-Backend-Fetch == "d1"
   expect resp.http.X-Backend-Deliver == "d1"
} -run
------------------------------------------------------------------------------------------------------

In Varnish 4 the following adapted test:

------------------------------------------------------------------------------------------------------
varnishtest "Test backends and directors"

server s1 {
   rxreq
   txresp -status 200
} -start


varnish v1 -vcl {
   import std;
   import directors;
   backend b1 {
     .host = "${s1_addr}";
     .port = "${s1_port}";
   }

   sub vcl_init {
     new d1 = directors.round_robin();
     d1.add_backend(b1);
   }

   sub vcl_recv {
     set req.backend_hint = d1.backend();
   }

   sub vcl_backend_response {
     if ( bereq.backend == d1 ) {
       set beresp.http.X-Backend-Response = "d1";
     }
   }

   sub vcl_deliver {
     if ( req.backend_hint == d1 ) {
       set resp.http.X-Backend-Deliver = "d1";
     }
   }

} -start

client c1 {
   txreq
   rxresp
   expect resp.status == 200
   expect resp.http.X-Backend-Response == "d1"
   expect resp.http.X-Backend-Deliver == "d1"
} -run
------------------------------------------------------------------------------------------------------

fails with this message:

**** v1    0.4 CLI RX| Message from VCC-compiler:\n
**** v1    0.4 CLI RX| Backend not found: 'd1'\n
**** v1    0.4 CLI RX| ('<vcl.inline>' Line 21 Pos 27)\n
**** v1    0.4 CLI RX|     if ( bereq.backend == d1 ) {\n
**** v1    0.4 CLI RX| --------------------------##----\n

and when we comment out the 'vcl_backend_response' sub it fails with 
this message:

**** v1    0.5 CLI RX| Message from VCC-compiler:\n
**** v1    0.5 CLI RX| Backend not found: 'd1'\n
**** v1    0.5 CLI RX| ('<vcl.inline>' Line 28 Pos 30)\n
**** v1    0.5 CLI RX|     if ( req.backend_hint == d1 ) {\n
**** v1    0.5 CLI RX| -----------------------------##----\n


When we change this test to compare against the backend directly and not 
against the director the test compiles

------------------------------------------------------------------------------------------------------
varnishtest "Test backends and directors"

server s1 {
   rxreq
   txresp -status 200
} -start


varnish v1 -vcl {
   import std;
   import directors;
   backend b1 {
     .host = "${s1_addr}";
     .port = "${s1_port}";
   }

   sub vcl_init {
     new d1 = directors.round_robin();
     d1.add_backend(b1);
   }

   sub vcl_recv {
     set req.backend_hint = d1.backend();
   }

   sub vcl_backend_response {
     std.log("xxxxxxxx-vcl_backend_response: " + bereq.backend);
     if ( bereq.backend == b1 ) {
       set beresp.http.X-Backend-Response = "d1";
     }
   }

   sub vcl_deliver {
     std.log("xxxxxxxx-vcl_deliver: " + req.backend_hint);
     if ( req.backend_hint == b1 ) {
       set resp.http.X-Backend-Deliver = "d1";
     }
   }

} -start

client c1 {
   txreq
   rxresp
   expect resp.status == 200
   expect resp.http.X-Backend-Response == "d1"
   expect resp.http.X-Backend-Deliver == "d1"
} -run
------------------------------------------------------------------------------------------------------

The test also fails because the expectations of the client are not met:

**   c1    1.0 === expect resp.http.X-Backend-Response == "d1"
---- c1    1.0 EXPECT resp.http.X-Backend-Response (<undef>) == "d1" failed

and we can see in the log that 'bereq.backend' and 'req.backend_hint' 
are set to 'd1'

...
**** v1    1.0 vsl|       1002 VCL_call        b BACKEND_RESPONSE
**** v1    1.0 vsl|       1002 VCL_Log         b 
xxxxxxxx-vcl_backend_response: d1
**** v1    1.0 vsl|       1002 VCL_return      b deliver
...
**** v1    1.0 vsl|       1001 VCL_call        c DELIVER
**** v1    1.0 vsl|       1001 VCL_Log         c xxxxxxxx-vcl_deliver: d1
**** v1    1.0 vsl|       1001 VCL_return      c deliver
...

The question is how to compare 'bereq.backend' and 'req.backend_hint' 
properly against a director/backend.
Are we missing something or is this a bug?


Thanks,

Ronald




More information about the varnish-misc mailing list