]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: server: add a max-reuse parameter
authorWilly Tarreau <w@1wt.eu>
Wed, 23 Jan 2019 09:21:49 +0000 (10:21 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 24 Jan 2019 18:06:43 +0000 (19:06 +0100)
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.

doc/configuration.txt
include/types/server.h
src/cfgparse.c
src/server.c

index 2a7efe96b18d670ca62e4f6444aaa6201e76d0e7..e44b6579d62bce30191622cd81a1fb120c125a36 100644 (file)
@@ -11826,6 +11826,16 @@ maxqueue <maxqueue>
   default value is "0" which means the queue is unlimited. See also the
   "maxconn" and "minconn" parameters.
 
+max-reuse <count>
+  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 <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
index 62c745dd293245a26c800cd8436fe0d4617fba21..e4371af0081bf12dd9d93f19a815f0e2828e1574 100644 (file)
@@ -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 */
 
index a12c4ee29f3c02d7f4c08edb75f5b12c0e186a28..05b6d9e581121b8d90ddd3814722ef9e58835423 100644 (file)
@@ -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;
index af0069668e0df976d8d7074cf21664db94a89904..50325de41ce1a32cab011ee8c1c5f883c907d011 100644 (file)
@@ -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 <value> 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;