mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-21 22:01:31 +02:00
MINOR: listener: support another thread dispatch mode: "fair"
This new algorithm for rebalancing incoming connections to multiple threads is simpler and instead of considering the threads load, it will only cycle through all of them, offering a fair share of the traffic to each thread. It may be well suited for short-lived connections but is also convenient for very large thread counts where it's not always certain that the least loaded thread will always be found.
This commit is contained in:
parent
6a4d48b736
commit
84fe1f479b
@ -3023,16 +3023,23 @@ tune.idletimer <timeout>
|
||||
clicking). There should be no reason for changing this value. Please check
|
||||
tune.ssl.maxrecord below.
|
||||
|
||||
tune.listener.multi-queue { on | off }
|
||||
Enables ('on') or disables ('off') the listener's multi-queue accept which
|
||||
spreads the incoming traffic to all threads a "bind" line is allowed to run
|
||||
on instead of taking them for itself. This provides a smoother traffic
|
||||
tune.listener.multi-queue { on | fair | off }
|
||||
Enables ('on' / 'fair') or disables ('off') the listener's multi-queue accept
|
||||
which spreads the incoming traffic to all threads a "bind" line is allowed to
|
||||
run on instead of taking them for itself. This provides a smoother traffic
|
||||
distribution and scales much better, especially in environments where threads
|
||||
may be unevenly loaded due to external activity (network interrupts colliding
|
||||
with one thread for example). This option is enabled by default, but it may
|
||||
be forcefully disabled for troubleshooting or for situations where it is
|
||||
estimated that the operating system already provides a good enough
|
||||
distribution and connections are extremely short-lived.
|
||||
with one thread for example). The default mode, "on", optimizes the choice of
|
||||
a thread by picking in a sample the one with the less connections. It is
|
||||
often the best choice when connections are long-lived as it manages to keep
|
||||
all threads busy. A second mode, "fair", instead cycles through all threads
|
||||
regardless of their instant load level. It can be better suited for short-
|
||||
lived connections, or on machines with very large numbers of threads where
|
||||
the probability to find the least loaded thread with the first mode is low.
|
||||
Finally it is possible to forcefully disable the redistribution mechanism
|
||||
using "off" for troubleshooting, or for situations where connections are
|
||||
short-lived and it is estimated that the operating system alredy provides a
|
||||
good enough distribution. The default is "on".
|
||||
|
||||
tune.lua.forced-yield <number>
|
||||
This directive forces the Lua engine to execute a yield each <number> of
|
||||
|
@ -66,7 +66,7 @@
|
||||
#define GTUNE_USE_SYSTEMD (1<<10)
|
||||
|
||||
#define GTUNE_BUSY_POLLING (1<<11)
|
||||
#define GTUNE_LISTENER_MQ (1<<12)
|
||||
/* unused: (1<<12) */
|
||||
#define GTUNE_SET_DUMPABLE (1<<13)
|
||||
#define GTUNE_USE_EVPORTS (1<<14)
|
||||
#define GTUNE_STRICT_LIMITS (1<<15)
|
||||
@ -81,6 +81,9 @@
|
||||
#define GTUNE_QUIC_SOCK_PER_CONN (1<<24)
|
||||
#define GTUNE_NO_QUIC (1<<25)
|
||||
#define GTUNE_USE_FAST_FWD (1<<26)
|
||||
#define GTUNE_LISTENER_MQ_FAIR (1<<27)
|
||||
#define GTUNE_LISTENER_MQ_OPT (1<<28)
|
||||
#define GTUNE_LISTENER_MQ_ANY (GTUNE_LISTENER_MQ_FAIR | GTUNE_LISTENER_MQ_OPT)
|
||||
|
||||
/* SSL server verify mode */
|
||||
enum {
|
||||
|
@ -187,7 +187,7 @@ struct global global = {
|
||||
}
|
||||
},
|
||||
.tune = {
|
||||
.options = GTUNE_LISTENER_MQ,
|
||||
.options = GTUNE_LISTENER_MQ_OPT,
|
||||
.bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)),
|
||||
.maxrewrite = MAXREWRITE,
|
||||
.reserved_bufs = RESERVED_BUFS,
|
||||
|
@ -1099,7 +1099,7 @@ void listener_accept(struct listener *l)
|
||||
|
||||
#if defined(USE_THREAD)
|
||||
mask = l->rx.bind_thread & _HA_ATOMIC_LOAD(&tg->threads_enabled);
|
||||
if (atleast2(mask) && (global.tune.options & GTUNE_LISTENER_MQ) && !stopping) {
|
||||
if (atleast2(mask) && (global.tune.options & GTUNE_LISTENER_MQ_ANY) && !stopping) {
|
||||
struct accept_queue_ring *ring;
|
||||
unsigned int t, t0, t1, t2;
|
||||
int base = tg->base;
|
||||
@ -1140,6 +1140,14 @@ void listener_accept(struct listener *l)
|
||||
t1 += my_ffsl(m1) - 1;
|
||||
}
|
||||
|
||||
/* if running in round-robin mode ("fair"), we don't need
|
||||
* to go further.
|
||||
*/
|
||||
if ((global.tune.options & GTUNE_LISTENER_MQ_ANY) == GTUNE_LISTENER_MQ_FAIR) {
|
||||
t = t1;
|
||||
goto updt_t1;
|
||||
}
|
||||
|
||||
if (unlikely(!(m2 & (1UL << t2)) || t1 == t2)) {
|
||||
/* highest bit not set */
|
||||
if (!m2)
|
||||
@ -1184,6 +1192,7 @@ void listener_accept(struct listener *l)
|
||||
}
|
||||
else {
|
||||
t = t1;
|
||||
updt_t1:
|
||||
t1++;
|
||||
if (t1 >= LONGBITS)
|
||||
t1 = 0;
|
||||
@ -1898,7 +1907,7 @@ static int bind_parse_thread(char **args, int cur_arg, struct proxy *px, struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* config parser for global "tune.listener.multi-queue", accepts "on" or "off" */
|
||||
/* config parser for global "tune.listener.multi-queue", accepts "on", "fair" or "off" */
|
||||
static int cfg_parse_tune_listener_mq(char **args, int section_type, struct proxy *curpx,
|
||||
const struct proxy *defpx, const char *file, int line,
|
||||
char **err)
|
||||
@ -1907,11 +1916,13 @@ static int cfg_parse_tune_listener_mq(char **args, int section_type, struct prox
|
||||
return -1;
|
||||
|
||||
if (strcmp(args[1], "on") == 0)
|
||||
global.tune.options |= GTUNE_LISTENER_MQ;
|
||||
global.tune.options = (global.tune.options & ~GTUNE_LISTENER_MQ_ANY) | GTUNE_LISTENER_MQ_OPT;
|
||||
else if (strcmp(args[1], "fair") == 0)
|
||||
global.tune.options = (global.tune.options & ~GTUNE_LISTENER_MQ_ANY) | GTUNE_LISTENER_MQ_FAIR;
|
||||
else if (strcmp(args[1], "off") == 0)
|
||||
global.tune.options &= ~GTUNE_LISTENER_MQ;
|
||||
global.tune.options &= ~GTUNE_LISTENER_MQ_ANY;
|
||||
else {
|
||||
memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]);
|
||||
memprintf(err, "'%s' expects either 'on', 'fair', or 'off' but got '%s'.", args[0], args[1]);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user