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.
This commit is contained in:
Willy Tarreau 2019-09-06 17:04:04 +02:00
parent d45d105428
commit ed5ac9c786

View File

@ -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);
}