MEDIUM: config: support per-listener backlog and maxconn
With SSL, connections are much more expensive, so it is important to be
able to limit concurrent connections per listener in order to limit the
memory usage.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 04f3900..00a5238 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -1471,11 +1471,12 @@
bind [<address>]:<port_range> [, ...]
bind [<address>]:<port_range> [, ...] interface <interface>
bind [<address>]:<port_range> [, ...] mss <maxseg>
+bind [<address>]:<port_range> [, ...] backlog <backlog>
+bind [<address>]:<port_range> [, ...] maxconn <maxconn>
bind [<address>]:<port_range> [, ...] transparent
bind [<address>]:<port_range> [, ...] id <id>
bind [<address>]:<port_range> [, ...] name <name>
bind [<address>]:<port_range> [, ...] defer-accept
-bind [<address>]:<port_range> [, ...] accept-proxy
bind /<path> [, ...]
bind /<path> [, ...] mode <mode>
bind /<path> [, ...] [ user <user> | uid <uid> ]
@@ -1545,6 +1546,17 @@
connection's advertised MSS for outgoing segments. This
parameter is only compatible with TCP sockets.
+ <backlog> sets the socket's backlog to this value. If unspecified, the
+ frontend's backlog is used instead.
+
+ <maxconn> limits the socket to this number of concurrent connections.
+ Extra connections will remain in the system's backlog until a
+ connection is released. If unspecified, the limit will be the
+ same as the frontend's maxconn. Note that in case of port
+ ranges, the same value will be applied to each socket. This
+ setting enables different limitations on expensive sockets,
+ for instance SSL entries which may easily eat all memory.
+
<id> is a persistent value for socket ID. Must be positive and
unique in the proxy. An unused value will automatically be
assigned if unset. Can only be used when defining only a
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 6ff166e..a150503 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1807,6 +1807,58 @@
#endif
}
+ if (!strcmp(args[cur_arg], "maxconn")) {
+ struct listener *l;
+ int val;
+
+ if (!*args[cur_arg + 1]) {
+ Alert("parsing [%s:%d] : '%s' : missing maxconn value.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ val = atol(args[cur_arg + 1]);
+ if (val <= 0) {
+ Alert("parsing [%s:%d] : '%s' : invalid maxconn value %d, must be > 0.\n",
+ file, linenum, args[0], val);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ for (l = curproxy->listen; l != last_listen; l = l->next)
+ l->maxconn = val;
+
+ cur_arg += 2;
+ continue;
+ }
+
+ if (!strcmp(args[cur_arg], "backlog")) {
+ struct listener *l;
+ int val;
+
+ if (!*args[cur_arg + 1]) {
+ Alert("parsing [%s:%d] : '%s' : missing backlog value.\n",
+ file, linenum, args[0]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ val = atol(args[cur_arg + 1]);
+ if (val <= 0) {
+ Alert("parsing [%s:%d] : '%s' : invalid backlog value %d, must be > 0.\n",
+ file, linenum, args[0], val);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ for (l = curproxy->listen; l != last_listen; l = l->next)
+ l->backlog = val;
+
+ cur_arg += 2;
+ continue;
+ }
+
if (!strcmp(args[cur_arg], "ssl")) { /* use ssl certificate */
#ifdef USE_OPENSSL
struct listener *l;
@@ -6888,8 +6940,10 @@
#endif /* USE_OPENSSL */
if (curproxy->options & PR_O_TCP_NOLING)
listener->options |= LI_O_NOLINGER;
- listener->maxconn = curproxy->maxconn;
- listener->backlog = curproxy->backlog;
+ if (!listener->maxconn)
+ listener->maxconn = curproxy->maxconn;
+ if (!listener->backlog)
+ listener->backlog = curproxy->backlog;
listener->timeout = &curproxy->timeout.client;
listener->accept = session_accept;
listener->frontend = curproxy;