5

I want to use the hash director in Varnish to redirect all requests for a same URL without query parameters to the same server:

For example,

http://example.com/foo/bar?a=1
http://example.com/foo/bar?a=2&b=3

Should hash to the same server. I want to hash on host and path only.

Here is my configuration:

sub vcl_init {
    new workers = directors.hash();

    workers.add_backend(worker_1, 1);
    workers.add_backend(worker_2, 1);
    workers.add_backend(worker_3, 1);
}

I understand I need to set the hash function here:

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

What should I put in there to hash on host + path, without query string?

BenMorel
  • 4,507
  • 10
  • 57
  • 85

1 Answers1

3

It doesn't look like the default VCL-provided req object provides a way to get the request path, without query parameters, just the full URL. Thus using some VMODs might help.

You might try using the QueryString VMOD, e.g. (from their docs):

import querystring;

sub vcl_hash {
    if (req.method == "GET" || req.method == "HEAD") {
        hash_data(querystring.remove(req.url));
    }
    else {
        hash_data(req.url);
    }
    hash_data(req.http.host);
    return (lookup);
}

And another nice VMOD, VSLP might also be of interest, given the increased control it provides over backend selection.

Using Varnish 4.1, you might be able to use:

sub vcl_recv {
    if (req.http.host) {
        set req.backend_hint = workers.backend(req.http.host + regsub(req.url, "\?.*$", ""));
    }
    else {
        set req.backend_hint = workers.backend(server.ip + regsub(req.url, "\?.*$", ""));
    }
}

Hope this helps!

Castaglia
  • 3,349
  • 3
  • 21
  • 42
  • I'm afraid the QueryString vmod doesn't support Varnish 4 at the moment. Also, I would be grateful if you could provide a turnkey configuration to match my requirements, i.e. what to put in `req.backend_hint`! – BenMorel Mar 19 '16 at 12:15
  • @Benjamin: I'll certainly try. Just to make sure: what's the exact Varnish version you're running? – Castaglia Mar 19 '16 at 16:27
  • At the moment I'm running 4.1! – BenMorel Mar 19 '16 at 21:12
  • Thanks for your updated answer, I'll need to test your suggestions before accepting it, in the meantime, enjoy the bounty! – BenMorel Mar 24 '16 at 23:18
  • 1
    For posterity: the correct syntax is `set req.backend_hint = workers.backend(req.http.host + regsub(req.url, "\?.*$", ""));`. Note the `+` instead of the `,` and `\?` instead of `?`. @Castaglia, maybe you want to update your answer? BTW, it works perfectly like that, thanks again! – BenMorel Dec 08 '17 at 18:02