[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;
}
/* 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
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;
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);
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