diff --git a/doc/configuration.txt b/doc/configuration.txt index 2a7efe96b..e44b6579d 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -11826,6 +11826,16 @@ maxqueue default value is "0" which means the queue is unlimited. See also the "maxconn" and "minconn" parameters. +max-reuse + The "max-reuse" argument indicates the HTTP connection processors that they + should not reuse a server connection more than this number of times to send + new requests. Permitted values are -1 (the default), which disables this + limit, or any positive value. Value zero will effectively disable keep-alive. + This is only used to work around certain server bugs which cause them to leak + resources over time. The argument is not necessarily respected by the lower + layers as there might be technical limitations making it impossible to + enforce. At least HTTP/2 connections to servers will respect it. + minconn When the "minconn" parameter is set, the maxconn limit becomes a dynamic limit following the backend's load. The server will always accept at least diff --git a/include/types/server.h b/include/types/server.h index 62c745dd2..e4371af00 100644 --- a/include/types/server.h +++ b/include/types/server.h @@ -225,6 +225,7 @@ struct server { unsigned int pool_purge_delay; /* Delay before starting to purge the idle conns pool */ unsigned int max_idle_conns; /* Max number of connection allowed in the orphan connections list */ unsigned int curr_idle_conns; /* Current number of orphan idling connections */ + int max_reuse; /* Max number of requests on a same connection */ struct task **idle_task; /* task responsible for cleaning idle orphan connections */ struct task *warmup; /* the task dedicated to the warmup when slowstart is set */ diff --git a/src/cfgparse.c b/src/cfgparse.c index a12c4ee29..05b6d9e58 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -471,6 +471,7 @@ void init_default_instance() defproxy.defsrv.maxqueue = 0; defproxy.defsrv.minconn = 0; defproxy.defsrv.maxconn = 0; + defproxy.defsrv.max_reuse = -1; defproxy.defsrv.max_idle_conns = -1; defproxy.defsrv.pool_purge_delay = 1000; defproxy.defsrv.slowstart = 0; diff --git a/src/server.c b/src/server.c index af0069668..50325de41 100644 --- a/src/server.c +++ b/src/server.c @@ -358,6 +358,20 @@ static int srv_parse_enabled(char **args, int *cur_arg, return 0; } +static int srv_parse_max_reuse(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err) +{ + char *arg; + + arg = args[*cur_arg + 1]; + if (!*arg) { + memprintf(err, "'%s' expects as argument.\n", args[*cur_arg]); + return ERR_ALERT | ERR_FATAL; + } + newsrv->max_reuse = atoi(arg); + + return 0; +} + static int srv_parse_pool_purge_delay(char **args, int *cur_arg, struct proxy *curproxy, struct server *newsrv, char **err) { const char *res; @@ -1239,6 +1253,7 @@ static struct srv_kw_list srv_kws = { "ALL", { }, { { "disabled", srv_parse_disabled, 0, 1 }, /* Start the server in 'disabled' state */ { "enabled", srv_parse_enabled, 0, 1 }, /* Start the server in 'enabled' state */ { "id", srv_parse_id, 1, 0 }, /* set id# of server */ + { "max-reuse", srv_parse_max_reuse, 1, 1 }, /* Set the max number of requests on a connection, -1 means unlimited */ { "namespace", srv_parse_namespace, 1, 1 }, /* Namespace the server socket belongs to (if supported) */ { "no-agent-check", srv_parse_no_agent_check, 0, 1 }, /* Do not enable any auxiliary agent check */ { "no-backup", srv_parse_no_backup, 0, 1 }, /* Flag as non-backup server */ @@ -1689,6 +1704,7 @@ static void srv_settings_cpy(struct server *srv, struct server *src, int srv_tmp srv->mux_proto = src->mux_proto; srv->pool_purge_delay = src->pool_purge_delay; srv->max_idle_conns = src->max_idle_conns; + srv->max_reuse = src->max_reuse; if (srv_tmpl) srv->srvrq = src->srvrq; @@ -1736,6 +1752,7 @@ struct server *new_server(struct proxy *proxy) srv->pool_purge_delay = 1000; srv->max_idle_conns = -1; + srv->max_reuse = -1; return srv;