[MEDIUM] stats: add support for changing frontend's maxconn at runtime

The new "set maxconn frontend XXX" statement on the stats socket allows
the admin to change a frontend's maxconn value. If some connections are
queued, they will immediately be accepted up to the new limit. If the
limit is lowered, new connections acceptation might be delayed. This can
be used to temporarily reduce or increase the impact of a specific frontend's
traffic on the whole process.
This commit is contained in:
Willy Tarreau 2011-08-02 11:49:05 +02:00
parent f5f3192e1e
commit 2a0f4d27a4
2 changed files with 71 additions and 0 deletions

View File

@ -9483,6 +9483,15 @@ prompt
quit
Close the connection when in interactive mode.
set maxconn frontend <frontend> <value>
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 <delay>
Change the CLI interface timeout for current connection. This can be useful
during long debugging sessions where the user needs to constantly inspect

View File

@ -48,6 +48,7 @@
#include <proto/freq_ctr.h>
#include <proto/log.h>
#include <proto/pipe.h>
#include <proto/protocols.h>
#include <proto/proto_uxst.h>
#include <proto/proxy.h>
#include <proto/session.h>
@ -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;
}