MINOR: mworker: support a configurable maximum number of reloads

This patch implements a new global parameter for the master-worker mode.
When setting the mworker-max-reloads value, a worker receive a SIGTERM
if its number of reloads is greater than this value.
This commit is contained in:
William Lallemand 2019-05-07 17:49:33 +02:00 committed by Willy Tarreau
parent f656279347
commit 27edc4b915
4 changed files with 60 additions and 0 deletions

View File

@ -571,6 +571,7 @@ The following keywords are supported in the "global" section :
- log-tag
- log-send-hostname
- lua-load
- mworker-max-reloads
- nbproc
- nbthread
- node
@ -966,6 +967,13 @@ master-worker [no-exit-on-failure]
See also "-W" in the management guide.
mworker-max-reloads <number>
In master-worker mode, this option limits the number of time a worker can
survive to a reload. If the worker did not left after a reload, once its
number of reloads is greater than this number, the worker will receive a
SIGTERM. This option helps to keep under control the number of workers.
See also "show proc" in the Management Guide.
nbproc <number>
Creates <number> processes when going daemon. This requires the "daemon"
mode. By default, only one process is created, which is the recommended mode

View File

@ -35,5 +35,6 @@ int mworker_child_nb();
int mworker_ext_launch_all();
void mworker_kill_max_reloads(int sig);
#endif /* PROTO_MWORKER_H_ */

View File

@ -2780,6 +2780,10 @@ int main(int argc, char **argv)
if (nb_oldpids && !(global.mode & MODE_MWORKER_WAIT))
nb_oldpids = tell_old_pids(oldpids_sig);
/* send a SIGTERM to workers who have a too high reloads number */
if ((global.mode & MODE_MWORKER) && !(global.mode & MODE_MWORKER_WAIT))
mworker_kill_max_reloads(SIGTERM);
if ((getenv("HAPROXY_MWORKER_REEXEC") == NULL)) {
nb_oldpids = 0;
free(oldpids);

View File

@ -17,6 +17,7 @@
#include <string.h>
#include <sys/wait.h>
#include <common/cfgparse.h>
#include <common/initcall.h>
#include <common/mini-clist.h>
@ -41,6 +42,7 @@
#endif
static int exitcode = -1;
static int max_reloads = -1; /* number max of reloads a worker can have until they are killed */
/* ----- children processes handling ----- */
@ -59,6 +61,16 @@ static void mworker_kill(int sig)
}
}
void mworker_kill_max_reloads(int sig)
{
struct mworker_proc *child;
list_for_each_entry(child, &proc_list, list) {
if (max_reloads != -1 && (child->options & PROC_O_TYPE_WORKER) &&
(child->pid > 0) && (child->reloads > max_reloads))
kill(child->pid, sig);
}
}
/* return 1 if a pid is a current child otherwise 0 */
int mworker_current_child(int pid)
@ -515,6 +527,41 @@ static int cli_parse_reload(char **args, char *payload, struct appctx *appctx, v
}
static int mworker_parse_global_max_reloads(char **args, int section_type, struct proxy *curpx,
struct proxy *defpx, const char *file, int linenum, char **err)
{
int err_code = 0;
if (alertif_too_many_args(1, file, linenum, args, &err_code))
goto out;
if (*(args[1]) == 0) {
memprintf(err, "%sparsing [%s:%d] : '%s' expects an integer argument.\n", *err, file, linenum, args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
max_reloads = atol(args[1]);
if (max_reloads < 0) {
memprintf(err, "%sparsing [%s:%d] '%s' : invalid value %d, must be >= 0", *err, file, linenum, args[0], max_reloads);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
out:
return err_code;
}
static struct cfg_kw_list mworker_kws = {{ }, {
{ CFG_GLOBAL, "mworker-max-reloads", mworker_parse_global_max_reloads },
{ 0, NULL, NULL },
}};
INITCALL1(STG_REGISTER, cfg_register_keywords, &mworker_kws);
/* register cli keywords */
static struct cli_kw_list cli_kws = {{ },{
{ { "@<relative pid>", NULL }, "@<relative pid> : send a command to the <relative pid> process", NULL, cli_io_handler_show_proc, NULL, NULL, ACCESS_MASTER_ONLY},