]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: balance uri: added 'whole' parameter to include query string in hash calculation
authorOskar Stolc <oskar.stolc@gmail.com>
Sat, 19 May 2012 09:19:54 +0000 (10:19 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 22 May 2012 05:56:54 +0000 (07:56 +0200)
This patch brings a new "whole" parameter to "balance uri" which makes
the hash work over the whole uri, not just the part before the query
string. Len and depth parameter are still honnored.

The reason for this new feature is explained below.

I have 3 backend servers, each accepting different form of HTTP queries:

http://backend1.server.tld/service1.php?q=...
http://backend1.server.tld/service2.php?q=...

http://backend2.server.tld/index.php?query=...&subquery=...

http://backend3.server.tld/image/49b8c0d9ff

Each backend server returns a different response based on either:
- the URI path (the left part of the URI before the question mark)
- the query string (the right part of the URI after the question mark)
- or the combination of both

I wanted to set up a common caching cluster (using 6 Squid servers, each
configured as reverse proxy for those 3 backends) and have HAProxy balance
the queries among the Squid servers based on URL. I also wanted to achieve
hight cache hit ration on each Squid server and send the same queries to
the same Squid servers. Initially I was considering using the 'balance uri'
algorithm, but that would not work as in case of backend2 all queries would
go to only one Squid server. The 'balance url_param' would not work either
as it would send the backend3 queries to only one Squid server.

So I thought the simplest solution would be to use 'balance uri', but to
calculate the hash based on the whole URI (URI path + query string),
instead of just the URI path.

doc/configuration.txt
include/types/proxy.h
src/backend.c

index 3fc77a0cad0214d9ae8972027bce090feff68f8a..1253357b0a6426f87dcb5118f25e1d4f5bf9eff7 100644 (file)
@@ -1311,18 +1311,20 @@ balance url_param <param> [check_post [<max_wait>]]
                   weight on the fly will have no effect, but this can be
                   changed using "hash-type".
 
-      uri         The left part of the URI (before the question mark) is hashed
-                  and divided by the total weight of the running servers. The
-                  result designates which server will receive the request. This
-                  ensures that a same URI will always be directed to the same
-                  server as long as no server goes up or down. This is used
-                  with proxy caches and anti-virus proxies in order to maximize
-                  the cache hit rate. Note that this algorithm may only be used
-                  in an HTTP backend. This algorithm is static by default,
-                  which means that changing a server's weight on the fly will
-                  have no effect, but this can be changed using "hash-type".
-
-                  This algorithm support two optional parameters "len" and
+      uri         This algorithm hashes either the left part of the URI (before
+                  the question mark) or the whole URI (if the "whole" parameter
+                  is present) and divides the hash value by the total weight of
+                  the running servers. The result designates which server will
+                  receive the request. This ensures that the same URI will
+                  always be directed to the same server as long as no server
+                  goes up or down. This is used with proxy caches and
+                  anti-virus proxies in order to maximize the cache hit rate.
+                  Note that this algorithm may only be used in an HTTP backend.
+                  This algorithm is static by default, which means that
+                  changing a server's weight on the fly will have no effect,
+                  but this can be changed using "hash-type".
+
+                  This algorithm supports two optional parameters "len" and
                   "depth", both followed by a positive integer number. These
                   options may be helpful when it is needed to balance servers
                   based on the beginning of the URI only. The "len" parameter
index a94eee7678da64ae2d518dfb675e6c3d66cd5ac4..622e1686c0d221248d58cc5da1c9637de50fcf41 100644 (file)
@@ -239,6 +239,7 @@ struct proxy {
        unsigned url_param_post_limit;          /* if checking POST body for URI parameter, max body to wait for */
        int  uri_len_limit;                     /* character limit for uri balancing algorithm */
        int  uri_dirs_depth1;                   /* directories+1 (slashes) limit for uri balancing algorithm */
+       int  uri_whole;                         /* if != 0, calculates the hash from the whole uri. Still honors the len_limit and dirs_depth1 */
        char *hh_name;                          /* name of the header parameter used for hashing */
        int  hh_len;                            /* strlen(hh_name), computed only once */
        int  hh_match_domain;                   /* toggle use of special match function */
index 31f1a0fbde6d98837a68800426a40604a221b31d..e3a64e91499c842fb2236e2f92e6922488cb3dc7 100644 (file)
@@ -167,7 +167,7 @@ struct server *get_server_uh(struct proxy *px, char *uri, int uri_len)
                        if (slashes == px->uri_dirs_depth1) /* depth+1 */
                                break;
                }
-               else if (c == '?')
+               else if (c == '?' && !px->uri_whole)
                        break;
 
                hash = c + (hash << 6) + (hash << 16) - hash;
@@ -1264,6 +1264,8 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
                curproxy->lbprm.algo &= ~BE_LB_ALGO;
                curproxy->lbprm.algo |= BE_LB_ALGO_UH;
 
+               curproxy->uri_whole = 0;
+
                while (*args[arg]) {
                        if (!strcmp(args[arg], "len")) {
                                if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
@@ -1284,8 +1286,12 @@ int backend_parse_balance(const char **args, char **err, struct proxy *curproxy)
                                curproxy->uri_dirs_depth1 = atoi(args[arg+1]) + 1;
                                arg += 2;
                        }
+                       else if (!strcmp(args[arg], "whole")) {
+                               curproxy->uri_whole = 1;
+                               arg += 1;
+                       }
                        else {
-                               memprintf(err, "%s only accepts parameters 'len' and 'depth' (got '%s').", args[0], args[arg]);
+                               memprintf(err, "%s only accepts parameters 'len', 'depth', and 'whole' (got '%s').", args[0], args[arg]);
                                return -1;
                        }
                }