From: Willy Tarreau Date: Fri, 6 Sep 2019 15:04:04 +0000 (+0200) Subject: BUG/MINOR: lb/leastconn: ignore the server weights for empty servers X-Git-Tag: v2.1-dev2~101 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed5ac9c78652bd2c75d1c535f54e6bf4191d232e;p=thirdparty%2Fhaproxy.git BUG/MINOR: lb/leastconn: ignore the server weights for empty servers As discussed in issue #178, the change brought around 1.9-dev11 by commit 1eb6c55808 ("MINOR: lb: make the leastconn algorithm more accurate") causes some harm in the situation it tried to improve. By always applying the server's weight even for no connection, we end up always picking the same servers for the first connections, so under a low load, if servers only have either 0 or 1 connections, in practice the same servers will always be picked. This patch partially restores the original behaviour but still keeping the spirit of the aforementioned patch. Now what is done is that servers with no connections will always be picked first, regardless of their weight, so they will effectively follow round-robin. Only servers with one connection or more will see an accurate weight applied. This patch was developed and tested by @malsumis and @jaroslawr who reported the initial issue. It should be backported to 2.0 and 1.9. --- diff --git a/src/lb_fwlc.c b/src/lb_fwlc.c index 5fa8173998..bd7793a914 100644 --- a/src/lb_fwlc.c +++ b/src/lb_fwlc.c @@ -48,13 +48,15 @@ static inline void fwlc_dequeue_srv(struct server *s) * for using #conns+1 is to sort by weights in case the server is picked * and not before it is picked. This provides a better load accuracy for * low connection counts when weights differ and makes sure the round-robin - * applies between servers of highest weight first. + * applies between servers of highest weight first. However servers with no + * connection are always picked first so that under low loads, it's not + * always the single server with the highest weight that gets picked. * * The server's lock and the lbprm's lock must be held. */ static inline void fwlc_queue_srv(struct server *s) { - s->lb_node.key = (s->served + 1) * SRV_EWGHT_MAX / s->next_eweight; + s->lb_node.key = s->served ? (s->served + 1) * SRV_EWGHT_MAX / s->next_eweight : 0; eb32_insert(s->lb_tree, &s->lb_node); }