mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-09 23:39:55 +00:00
OPTIM: backend: skip LB when we know the backend is full
For some algos (roundrobin, static-rr, leastconn, first) we know that if there is any request queued in the backend, it's because a previous attempt failed at finding a suitable server after trying all of them. This alone is sufficient to decide that the next request will skip the LB algo and directly reach the backend's queue. Doing this alone avoids an O(N) lookup when load-balancing on a saturated farm of N servers, which starts to be very expensive for hundreds of servers, especially under the lbprm lock. This change alone has increased the request rate from 110k to 148k RPS for 200 saturated servers on 8 threads, and fwlc_reposition_srv() doesn't show up anymore in perf top. See github issue #880 for more context. It could have been the same for random, except that random is performed using a consistent hash and it only considers a small set of servers (2 by default), so it may result in queueing at the backend despite having some free slots on unknown servers. It's no big deal though since random() only performs two attempts by default. For hashing algorithms this is pointless since we don't queue at the backend, except when there's no hash key found, which is the least of our concerns here.
This commit is contained in:
parent
b88ae18021
commit
82cd5c13a5
@ -640,14 +640,25 @@ int assign_server(struct stream *s)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (s->be->lbprm.algo & BE_LB_KIND) {
|
||||
|
||||
if (s->be->lbprm.algo & BE_LB_KIND) {
|
||||
/* we must check if we have at least one server available */
|
||||
if (!s->be->lbprm.tot_weight) {
|
||||
err = SRV_STATUS_NOSRV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* if there's some queue on the backend, with certain algos we
|
||||
* 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_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;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* First check whether we need to fetch some data or simply call
|
||||
* the LB lookup function. Only the hashing functions will need
|
||||
* some input data in fact, and will support multiple algorithms.
|
||||
|
Loading…
Reference in New Issue
Block a user