How to hash based on host + path in Varnish

varnish

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?

Best Answer

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!

Related Topic