[PATCH] : Prevent redispatcher from selecting the same server

From: Krzysztof Oledzki <ole#ans.pl>
Date: Wed, 26 Dec 2007 02:45:17 +0100


[RFC]: Prevent redispatcher from selecting the same server

When haproxy decides that session needs to be redispatched it chose a server, but there is no guarantee for it to be a different one. So, it often happens that selected server is exactly the same that it was previously, so a client ends up with a 503 error anyway, especially when one sever has much bigger weight than others.

This RFC quality patch fix RR and PH algos, so when a redispatching occures assign_server() never selects previously assigned server again.

TODO: SH/UH, test PH, more tests

diff --git a/include/proto/backend.h b/include/proto/backend.h index 444e53a..6e8a5f4 100644
--- a/include/proto/backend.h
+++ b/include/proto/backend.h
@@ -50,7 +50,7 @@ void fwrr_init_server_groups(struct proxy *p);

 	do {
 		srv = px->lbprm.map.srv[newidx++];
-		if (!srv->maxconn || srv->cur_sess < srv_dynamic_maxconn(srv)) {
+		if (srv != esrv && (!srv->maxconn || srv->cur_sess < srv_dynamic_maxconn(srv))) {
 			px->lbprm.map.rr_idx = newidx;
 			return srv;
 		}

diff --git a/src/backend.c b/src/backend.c index e9fe544..e746bfc 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -730,7 +730,7 @@ static inline void fwrr_update_position(struct fwrr_group *grp, struct server *s

                 /* the server is saturated, let's chain it for later reinsertion */
@@ -822,9 +822,10 @@ static struct server *fwrr_get_next_server(struct proxy *p)

@@ -861,7 +862,11 @@ struct server *get_server_ph(struct proxy *px, const char *uri, int uri_len)

 					uri_len--;
 					p++;
 				}
-				return px->lbprm.map.srv[hash % px->lbprm.tot_weight];
+				srv = px->lbprm.map.srv[hash % px->lbprm.tot_weight];
+				if (srv!=esrv)
+					return srv;
+				else
+					return NULL;
 			}
 		}
 

@@ -917,7 +922,7 @@ int assign_server(struct session *s)
 

 			switch (s->be->lbprm.algo & BE_LB_ALGO) {
 			case BE_LB_ALGO_RR:
-				s->srv = fwrr_get_next_server(s->be);
+				s->srv = fwrr_get_next_server(s->be, s->srv);
 				if (!s->srv)
 					return SRV_STATUS_FULL;
 				break;

@@ -943,10 +948,10 @@ int assign_server(struct session *s)
/* URL Parameter hashing */ s->srv = get_server_ph(s->be, s->txn.req.sol + s->txn.req.sl.rq.u, - s->txn.req.sl.rq.u_l); + s->txn.req.sl.rq.u_l, s->srv); if (!s->srv) { /* parameter not found, fall back to round robin on the map */ - s->srv = get_server_rr_with_conns(s->be); + s->srv = get_server_rr_with_conns(s->be, s->srv); if (!s->srv) return SRV_STATUS_FULL; }
@@ -1063,7 +1068,7 @@ int assign_server_and_queue(struct session *s)
if (s->flags & SN_ASSIGNED) { if (s->srv && s->srv->maxqueue > 0 && s->srv->nbpend >= s->srv->maxqueue) { s->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET); - s->srv = NULL; + s->flags |= SN_REDISP; http_flush_cookie_flags(&s->txn); } else { /* a server does not need to be assigned, perhaps because we're in

@@ -1427,7 +1432,6 @@ int srv_retryable_connect(struct session *t)
 
 	t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 	t->flags |= SN_REDISP;
-	t->srv = NULL; /* it's left to the dispatcher to choose a server */
 	http_flush_cookie_flags(&t->txn);
 	return 0;

 }
diff --git a/src/checks.c b/src/checks.c index c631946..ebb7b44 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -78,7 +78,6 @@ static int redistribute_pending(struct server *s)
 			sess->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 			sess->flags |= SN_REDISP;
 
-			sess->srv = NULL; /* it's left to the dispatcher to choose a server */
 			http_flush_cookie_flags(&sess->txn);
 			pendconn_free(pc);
 			task_wakeup(sess->task);

diff --git a/src/proto_http.c b/src/proto_http.c index ec46501..8bbd1cc 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2515,7 +2515,6 @@ int process_srv(struct session *t)
 
 				t->flags &= ~(SN_DIRECT | SN_ASSIGNED | SN_ADDR_SET);
 				t->flags |= SN_REDISP;
-				t->srv = NULL; /* it's left to the dispatcher to choose a server */
 				http_flush_cookie_flags(txn);
 
 				/* first, get a connection */
Received on 2007/12/26 02:45

This archive was generated by hypermail 2.2.0 : 2007/12/26 03:00 CET