From 8ae8c48eb0d3f5f8feddabc4e74956e7bb83ee6f Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Thu, 22 Oct 2020 17:19:07 +0200 Subject: [PATCH] MEDIUM: fwlc: re-enable per-server queuing up to maxqueue Leastconn has the nice propery of being able to sort servers by their current usage. It's really a shame to force all requests into the backend queue when the algo would be able to also consider their current queue. In order not to change existing behavior but extend it, this patch allows leastconn to elect servers which are already full if they have an explicitly configured maxqueue setting above zero and their queue hasn't reached that threshold. This will significantly reduce the pressure in the backend queue when queuing a lot with lots of servers. A test on 8 threads with 100 servers configured with maxconn 1 jumped from 165krps to 330krps with maxqueue 15 with this patch. This partially undoes commit 82cd5c13a ("OPTIM: backend: skip LB when we know the backend is full") but allows to scale much better even by setting a single-digit maxqueue value. Some better heuristics could be used to maintain the behavior of the bypass in the patch above, consisting in keeping it if it's known that there is no server with a configured maxqueue in the farm (or in the backend). --- doc/configuration.txt | 10 +++++++--- src/backend.c | 2 +- src/lb_fwlc.c | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 6116f25d3..4d413be5f 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -13452,9 +13452,13 @@ maxqueue will wait in the queue for this server. If this limit is reached, next requests will be redispatched to other servers instead of indefinitely waiting to be served. This will break persistence but may allow people to - quickly re-log in when the server they try to connect to is dying. The - default value is "0" which means the queue is unlimited. See also the - "maxconn" and "minconn" parameters. + quickly re-log in when the server they try to connect to is dying. Some load + balancing algorithms such as leastconn take this into account and accept to + add requests into a server's queue up to this value if it is explicitly set + to a value greater than zero, which often allows to better smooth the load + when dealing with single-digit maxconn values. The default value is "0" which + means the queue is unlimited. See also the "maxconn" and "minconn" parameters + and "balance leastconn". max-reuse The "max-reuse" argument indicates the HTTP connection processors that they diff --git a/src/backend.c b/src/backend.c index 34e5e7aac..e0f7dd627 100644 --- a/src/backend.c +++ b/src/backend.c @@ -652,7 +652,7 @@ int assign_server(struct stream *s) * know it's because all servers are full. */ if (s->be->nbpend && - (((s->be->lbprm.algo & BE_LB_KIND) == BE_LB_KIND_CB) || // conn-based: leastconn & first + (((s->be->lbprm.algo & (BE_LB_KIND|BE_LB_NEED|BE_LB_PARM)) == BE_LB_ALGO_FAS)|| // first ((s->be->lbprm.algo & (BE_LB_KIND|BE_LB_NEED|BE_LB_PARM)) == BE_LB_ALGO_RR) || // roundrobin ((s->be->lbprm.algo & (BE_LB_KIND|BE_LB_NEED|BE_LB_PARM)) == BE_LB_ALGO_SRR))) { // static-rr err = SRV_STATUS_FULL; diff --git a/src/lb_fwlc.c b/src/lb_fwlc.c index c7e0dd801..bf5ae61a7 100644 --- a/src/lb_fwlc.c +++ b/src/lb_fwlc.c @@ -323,7 +323,7 @@ struct server *fwlc_get_next_server(struct proxy *p, struct server *srvtoavoid) struct server *s; s = eb32_entry(node, struct server, lb_node); - if (!s->maxconn || (!s->nbpend && s->served < srv_dynamic_maxconn(s))) { + if (!s->maxconn || s->served + s->nbpend < srv_dynamic_maxconn(s) + s->maxqueue) { if (s != srvtoavoid) { srv = s; break;