From: Willy Tarreau Date: Wed, 23 Jan 2019 09:21:49 +0000 (+0100) Subject: MINOR: server: add a max-reuse parameter X-Git-Tag: v2.0-dev1~159 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9c538e01c2e9d4b7120e96df35447ef08533eb71;p=thirdparty%2Fhaproxy.git MINOR: server: add a max-reuse parameter Some servers may wish to limit the total number of requests they execute over a connection because some of their components might leak resources. In HTTP/1 it was easy, they just had to emit a "connection: close" header field with the last response. In HTTP/2, it's less easy because the info is not always shared with the component dealing with the H2 protocol and it could be harder to advertise a GOAWAY with a stream limit. This patch provides a solution to this by adding a new "max-reuse" parameter to the server keyword. This parameter indicates how many times an idle connection may be reused for new requests. The information is made available and the underlying muxes will be able to use it at will. This patch should be backported to 1.9. --- diff --git a/doc/configuration.txt b/doc/configuration.txt index 2a7efe96b1..e44b6579d6 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 62c745dd29..e4371af008 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 a12c4ee29f..05b6d9e581 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 af0069668e..50325de41c 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;