diff --git a/doc/configuration.txt b/doc/configuration.txt index aedced58d..cd6ddf68b 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1638,6 +1638,17 @@ tune.idletimer clicking). There should be not 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 + 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. + tune.lua.forced-yield This directive forces the Lua engine to execute a yield each of instructions executed. This permits interrupting a long script and allows the diff --git a/include/types/global.h b/include/types/global.h index b26553bc2..503d8f988 100644 --- a/include/types/global.h +++ b/include/types/global.h @@ -70,6 +70,7 @@ #define GTUNE_USE_SYSTEMD (1<<10) #define GTUNE_BUSY_POLLING (1<<11) +#define GTUNE_LISTENER_MQ (1<<12) /* Access level for a stats socket */ #define ACCESS_LVL_NONE 0 diff --git a/src/haproxy.c b/src/haproxy.c index 9ae093918..c9aaa236f 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -150,6 +150,7 @@ struct global global = { } }, .tune = { + .options = GTUNE_LISTENER_MQ, .bufsize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)), .maxrewrite = -1, .chksize = (BUFSIZE + 2*sizeof(void *) - 1) & -(2*sizeof(void *)), diff --git a/src/listener.c b/src/listener.c index 0d7a1c480..504cbbf38 100644 --- a/src/listener.c +++ b/src/listener.c @@ -818,7 +818,7 @@ void listener_accept(int fd) #if defined(USE_THREAD) count = l->bind_conf->thr_count; - if (count > 1) { + if (count > 1 && (global.tune.options & GTUNE_LISTENER_MQ)) { struct accept_queue_ring *ring; int r, t1, t2, q1, q2; @@ -1272,6 +1272,25 @@ static int bind_parse_proto(char **args, int cur_arg, struct proxy *px, struct b return 0; } +/* config parser for global "tune.listener.multi-queue", accepts "on" or "off" */ +static int cfg_parse_tune_listener_mq(char **args, int section_type, struct proxy *curpx, + struct proxy *defpx, const char *file, int line, + char **err) +{ + if (too_many_args(1, args, err, NULL)) + return -1; + + if (strcmp(args[1], "on") == 0) + global.tune.options |= GTUNE_LISTENER_MQ; + else if (strcmp(args[1], "off") == 0) + global.tune.options &= ~GTUNE_LISTENER_MQ; + else { + memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]); + return -1; + } + return 0; +} + /* Note: must not be declared as its list will be overwritten. * Please take care of keeping this list alphabetically sorted. */ @@ -1314,6 +1333,14 @@ static struct bind_kw_list bind_kws = { "ALL", { }, { INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws); +/* config keyword parsers */ +static struct cfg_kw_list cfg_kws = {ILH, { + { CFG_GLOBAL, "tune.listener.multi-queue", cfg_parse_tune_listener_mq }, + { 0, NULL, NULL } +}}; + +INITCALL1(STG_REGISTER, cfg_register_keywords, &cfg_kws); + /* * Local variables: * c-indent-level: 8