[MEDIUM] add support for URI hash depth and length limits

This patch adds two optional arguments "len" and "depth" to
"balance uri". They are used to limit the length in characters
of the analysis, as well as the number of directory components
it applies to.
This commit is contained in:
Marek Majkowski 2008-04-27 23:25:55 +02:00 committed by Willy Tarreau
parent e7dd2f29b9
commit 9c30fc161f
4 changed files with 59 additions and 4 deletions

View File

@ -745,6 +745,20 @@ balance url_param <param> [check_post [<max_wait>]]
that changing a server's weight on the fly will have no
effect.
This algorithm support 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
indicates that the algorithm should only consider that many
characters at the beginning of the URI to compute the hash.
Note that having "len" set to 1 rarely makes sense since most
URIs start with a leading "/".
The "depth" parameter indicates the maximum directory depth
to be used to compute the hash. One level is counted for each
slash in the request. If both parameters are specified, the
evaluation stops when either is reached.
url_param The URL parameter specified in argument will be looked up in
the query string of each HTTP GET request.
@ -783,9 +797,10 @@ balance url_param <param> [check_post [<max_wait>]]
server's weight on the fly will have no effect.
<arguments> is an optional list of arguments which may be needed by some
algorithms. Right now, only the "url_param" algorithm supports
an optional argument.
algorithms. Right now, only "url_param" and "uri" support an
optional argument.
balance uri [len <len>] [depth <depth>]
balance url_param <param> [check_post [<max_wait>]]
The definition of the load balancing algorithm is mandatory for a backend

View File

@ -159,6 +159,7 @@ static inline struct server *get_server_uh(struct proxy *px, char *uri, int uri_
{
unsigned long hash = 0;
int c;
int slashes = 0;
if (px->lbprm.tot_weight == 0)
return NULL;
@ -166,10 +167,19 @@ static inline struct server *get_server_uh(struct proxy *px, char *uri, int uri_
if (px->lbprm.map.state & PR_MAP_RECALC)
recalc_server_map(px);
if (px->uri_len_limit)
uri_len = MIN(uri_len, px->uri_len_limit);
while (uri_len--) {
c = *uri++;
if (c == '?')
if (c == '/') {
slashes++;
if (slashes == px->uri_dirs_depth1) /* depth+1 */
break;
}
else if (c == '?')
break;
hash = c + (hash << 6) + (hash << 16) - hash;
}

View File

@ -166,6 +166,8 @@ struct proxy {
char *url_param_name; /* name of the URL parameter used for hashing */
int url_param_len; /* strlen(url_param_name), computed only once */
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 */
char *appsession_name; /* name of the cookie to look for */
int appsession_name_len; /* strlen(appsession_name), computed only once */
int appsession_len; /* length of the appsession cookie value to be used */

View File

@ -1973,8 +1973,36 @@ int backend_parse_balance(const char **args, char *err, int errlen, struct proxy
curproxy->lbprm.algo |= BE_LB_ALGO_SH;
}
else if (!strcmp(args[0], "uri")) {
int arg = 1;
curproxy->lbprm.algo &= ~BE_LB_ALGO;
curproxy->lbprm.algo |= BE_LB_ALGO_UH;
while (*args[arg]) {
if (!strcmp(args[arg], "len")) {
if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
snprintf(err, errlen, "'balance uri len' expects a positive integer (got '%s').", args[arg+1]);
return -1;
}
curproxy->uri_len_limit = atoi(args[arg+1]);
arg += 2;
}
else if (!strcmp(args[arg], "depth")) {
if (!*args[arg+1] || (atoi(args[arg+1]) <= 0)) {
snprintf(err, errlen, "'balance uri depth' expects a positive integer (got '%s').", args[arg+1]);
return -1;
}
/* hint: we store the position of the ending '/' (depth+1) so
* that we avoid a comparison while computing the hash.
*/
curproxy->uri_dirs_depth1 = atoi(args[arg+1]) + 1;
arg += 2;
}
else {
snprintf(err, errlen, "'balance uri' only accepts parameters 'len' and 'depth' (got '%s').", args[arg]);
return -1;
}
}
}
else if (!strcmp(args[0], "url_param")) {
if (!*args[1]) {
@ -1987,7 +2015,7 @@ int backend_parse_balance(const char **args, char *err, int errlen, struct proxy
free(curproxy->url_param_name);
curproxy->url_param_name = strdup(args[1]);
curproxy->url_param_len = strlen(args[1]);
if ( *args[2] ) {
if (*args[2]) {
if (strcmp(args[2], "check_post")) {
snprintf(err, errlen, "'balance url_param' only accepts check_post modifier.");
return -1;