--- tomcat-connectors/native/common/jk_lb_worker.c (revision 989196) +++ tomcat-connectors/native/common/jk_lb_worker.c (working copy) @@ -65,6 +65,7 @@ JK_LB_METHOD_TEXT_TRAFFIC, JK_LB_METHOD_TEXT_BUSYNESS, JK_LB_METHOD_TEXT_SESSIONS, + JK_LB_METHOD_TEXT_HASH, "unknown", NULL }; @@ -185,6 +186,8 @@ return JK_LB_METHOD_BUSYNESS; else if (*v == 's' || *v == 'S' || *v == '3') return JK_LB_METHOD_SESSIONS; + else if (*v == 'h' || *v == 'H' || *v == '4') + return JK_LB_METHOD_HASH; else return JK_LB_METHOD_DEF; } @@ -447,7 +450,7 @@ ++id_start; if (*id_start == '=' && id_start[1]) { /* - * Session cookie was found, get it's value + * Session cookie was found, get its value */ char *id_end; size_t sz; @@ -755,7 +755,54 @@ return candidate; } +unsigned long hash(char *str) +{ + unsigned long h = 0, g; + while ( *str ) { + h = ( h << 4 ) + *str++; + if (( g = h & 0xF0000000 )) + h ^= g >> 24; + h &= ~g; + } + + return h; +} + +static int find_best_byhash(jk_ws_service_t *s, + lb_worker_t *p, + int *states, + jk_logger_t *l) +{ + unsigned long h; + unsigned int i; + char req[256]; + + int candidate = -1; + int activation; + lb_sub_worker_t wr; + + strncpy(req, s->req_uri, 256); + strncpy(req, s->query_string, 256); + + /* hash the request, return appropriate worker */ + h = hash(req); + srand(h); //seed with hash + i = rand() % p->num_of_workers; + + wr = p->lb_workers[i]; + activation = s->extension.activation ? + s->extension.activation[i] : + JK_LB_ACTIVATION_UNSET; + if (activation == JK_LB_ACTIVATION_UNSET) + activation = wr.activation; + + if (JK_WORKER_USABLE(states[wr.i], activation)) + candidate = i; + return candidate; +} + + static int find_best_byvalue(jk_ws_service_t *s, lb_worker_t *p, int *states, @@ -888,7 +935,14 @@ { int rc = -1; - rc = find_best_byvalue(s, p, states, l); + /* Try byhash first, if enabled */ + if (p->lbmethod == JK_LB_METHOD_HASH) + rc = find_best_byhash(s, p, states, l); + /* If byhash didn't work (disabled, or error on hashed worker), + fall back to default byvalue */ + if (rc < 0) + rc = find_best_byvalue(s, p, states, l); + /* By default use worker route as session route */ if (rc < 0) rc = find_failover_worker(s, p, states, l); --- tomcat-connectors/native/common/jk_lb_worker.h (revision 989196) +++ tomcat-connectors/native/common/jk_lb_worker.h (working copy) @@ -44,12 +44,14 @@ #define JK_LB_METHOD_TRAFFIC (1) #define JK_LB_METHOD_BUSYNESS (2) #define JK_LB_METHOD_SESSIONS (3) +#define JK_LB_METHOD_HASH (4) #define JK_LB_METHOD_DEF (JK_LB_METHOD_REQUESTS) -#define JK_LB_METHOD_MAX (JK_LB_METHOD_SESSIONS) +#define JK_LB_METHOD_MAX (JK_LB_METHOD_HASH) #define JK_LB_METHOD_TEXT_REQUESTS ("Request") #define JK_LB_METHOD_TEXT_TRAFFIC ("Traffic") #define JK_LB_METHOD_TEXT_BUSYNESS ("Busyness") #define JK_LB_METHOD_TEXT_SESSIONS ("Sessions") +#define JK_LB_METHOD_TEXT_HASH ("Hash") #define JK_LB_METHOD_TEXT_DEF (JK_LB_METHOD_TEXT_REQUESTS) #define JK_LB_LOCK_OPTIMISTIC (0) #define JK_LB_LOCK_PESSIMISTIC (1)