diff --git a/doc/configuration.txt b/doc/configuration.txt index dd166e775..89b985fb8 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -682,6 +682,7 @@ The following keywords are supported in the "global" section : - tune.http.cookielen - tune.http.logurilen - tune.http.maxhdr + - tune.idle-pool.shared - tune.idletimer - tune.lua.forced-yield - tune.lua.maxmem @@ -1949,6 +1950,15 @@ tune.http.maxhdr 1..32767. Keep in mind that each new header consumes 32bits of memory for each session, so don't push this limit too high. +tune.idle-pool.shared { on | off } + Enables ('on') or disables ('off') sharing of idle connection pools between + threads for a same server. The default is to share them between threads in + order to minimize the number of persistent connections to a server, and to + optimize the connection reuse rate. But to help with debugging or when + suspecting a bug in HAProxy around connection reuse, it can be convenient to + forcefully disable this idle pool sharing between multiple threads, and force + this option to "off". The default is on. + tune.idletimer Sets the duration after which haproxy will consider that an empty buffer is probably associated with an idle stream. This is used to optimally adjust diff --git a/include/haproxy/global-t.h b/include/haproxy/global-t.h index 0da246dde..677d98f51 100644 --- a/include/haproxy/global-t.h +++ b/include/haproxy/global-t.h @@ -68,6 +68,7 @@ #define GTUNE_INSECURE_SETUID (1<<17) #define GTUNE_FD_ET (1<<18) #define GTUNE_SCHED_LOW_LATENCY (1<<19) +#define GTUNE_IDLE_POOL_SHARED (1<<20) /* SSL server verify mode */ enum { diff --git a/src/backend.c b/src/backend.c index 0b4cb4c93..f87940be8 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1107,6 +1107,10 @@ static struct connection *conn_backend_get(struct server *srv, int is_safe) if (conn) goto done; + /* pool sharing globally disabled ? */ + if (!(global.tune.options & GTUNE_IDLE_POOL_SHARED)) + goto done; + /* Are we allowed to pick from another thread ? We'll still try * it if we're running low on FDs as we don't want to create * extra conns in this case, otherwise we can give up if we have diff --git a/src/haproxy.c b/src/haproxy.c index c8c869a6f..e733d454d 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1788,6 +1788,9 @@ static void init(int argc, char **argv) #if defined(SO_REUSEPORT) global.tune.options |= GTUNE_USE_REUSEPORT; #endif +#ifdef USE_THREAD + global.tune.options |= GTUNE_IDLE_POOL_SHARED; +#endif pid = getpid(); progname = *argv; diff --git a/src/server.c b/src/server.c index ac32e1c25..a016b7bd9 100644 --- a/src/server.c +++ b/src/server.c @@ -5333,6 +5333,25 @@ remove: return task; } +/* config parser for global "tune.idle-pool.shared", accepts "on" or "off" */ +static int cfg_parse_idle_pool_shared(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_IDLE_POOL_SHARED; + else if (strcmp(args[1], "off") == 0) + global.tune.options &= ~GTUNE_IDLE_POOL_SHARED; + else { + memprintf(err, "'%s' expects either 'on' or 'off' but got '%s'.", args[0], args[1]); + return -1; + } + return 0; +} + /* config parser for global "tune.pool-{low,high}-fd-ratio" */ static int cfg_parse_pool_fd_ratio(char **args, int section_type, struct proxy *curpx, struct proxy *defpx, const char *file, int line, @@ -5360,6 +5379,7 @@ static int cfg_parse_pool_fd_ratio(char **args, int section_type, struct proxy * /* config keyword parsers */ static struct cfg_kw_list cfg_kws = {ILH, { + { CFG_GLOBAL, "tune.idle-pool.shared", cfg_parse_idle_pool_shared }, { CFG_GLOBAL, "tune.pool-high-fd-ratio", cfg_parse_pool_fd_ratio }, { CFG_GLOBAL, "tune.pool-low-fd-ratio", cfg_parse_pool_fd_ratio }, { 0, NULL, NULL }