diff --git a/doc/configuration.txt b/doc/configuration.txt index 537ab6f74..cd5f979eb 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -9483,6 +9483,15 @@ prompt quit Close the connection when in interactive mode. +set maxconn frontend + Dynamically change the specified frontend's maxconn setting. Any non-null + positive value is allowed, but setting values larger than the global maxconn + does not make much sense. If the limit is increased and connections were + pending, they will immediately be accepted. If it is lowered to a value below + the current number of connections, new connections acceptation will be + delayed until the threshold is reached. The frontend might be specified by + either its name or its numeric ID prefixed with a sharp ('#'). + set timeout cli Change the CLI interface timeout for current connection. This can be useful during long debugging sessions where the user needs to constantly inspect diff --git a/src/dumpstats.c b/src/dumpstats.c index 9caebdd59..9c8922609 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include #include @@ -83,6 +84,7 @@ static const char stats_sock_usage_msg[] = " set timeout : change a timeout setting\n" " disable server : set a server in maintenance mode\n" " enable server : re-enable a server that was previously in maintenance mode\n" + " set maxconn : change a maxconn setting\n" ""; static const char stats_permission_denied_msg[] = @@ -958,6 +960,66 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line) return 1; } } + else if (strcmp(args[1], "maxconn") == 0) { + if (strcmp(args[2], "frontend") == 0) { + struct proxy *px; + struct listener *l; + int v; + + if (s->listener->perm.ux.level < ACCESS_LVL_ADMIN) { + si->applet.ctx.cli.msg = stats_permission_denied_msg; + si->applet.st0 = STAT_CLI_PRINT; + return 1; + } + + if (!*args[3]) { + si->applet.ctx.cli.msg = "Frontend name expected.\n"; + si->applet.st0 = STAT_CLI_PRINT; + return 1; + } + + px = findproxy(args[3], PR_CAP_FE); + if (!px) { + si->applet.ctx.cli.msg = "No such frontend.\n"; + si->applet.st0 = STAT_CLI_PRINT; + return 1; + } + + if (!*args[4]) { + si->applet.ctx.cli.msg = "Integer value expected.\n"; + si->applet.st0 = STAT_CLI_PRINT; + return 1; + } + + v = atoi(args[4]); + /* check for unlimited values, we restore default setting (cfg_maxpconn) */ + if (v < 1) { + si->applet.ctx.cli.msg = "Value out of range.\n"; + si->applet.st0 = STAT_CLI_PRINT; + return 1; + } + + /* OK, the value is fine, so we assign it to the proxy and to all of + * its listeners. The blocked ones will be dequeued. + */ + px->maxconn = v; + for (l = px->listen; l != NULL; l = l->next) { + l->maxconn = v; + if (l->state == LI_FULL) + resume_listener(l); + } + + if (px->maxconn > px->feconn && !LIST_ISEMPTY(&s->fe->listener_queue)) + dequeue_all_listeners(&s->fe->listener_queue); + + return 1; + } + else { + si->applet.ctx.cli.msg = "'set maxconn' only supports 'frontend'.\n"; + si->applet.st0 = STAT_CLI_PRINT; + return 1; + } + } else { /* unknown "set" parameter */ return 0; }