* HAPROXY_CLI
* HAPROXY_MASTER_CLI
* HAPROXY_MASTER_ID
+ * HAPROXY_WORKER_ID
* HAPROXY_LOCALPEER
Their values are undefined during configuration parsing, they are set later
| HAPROXY_CLI | | | | | | X |
| HAPROXY_MASTER_CLI | | | | | X | |
| HAPROXY_MASTER_ID | | X | | | X | X |
+ | HAPROXY_WORKER_ID | | X | | | | X |
| HAPROXY_LOCALPEER | | X | | | | X |
| HAPROXY_HTTP_LOG_FMT | | X | | X | | |
| HAPROXY_HTTP_CLF_LOG_FMT | | X | | X | | |
the one of the proxies' and servers' "guid": at most 127 characters among
letters, digits, '.', ':', '-' and '_'.
+ * HAPROXY_WORKER_ID: unique identifier of the worker process. It is randomly
+ generated at boot on the worker process, and may be overwritten by the
+ "worker-id" keyword in the global section. The generated random is changed
+ on every reload.
+
+ Its format is the same as the one of HAPROXY_MASTER_ID above. It is
+ set before the worker reads the rest of its configuration, so it may be
+ referenced from there, and being part of the process' environment it is
+ also visible to Lua (os.getenv()) and inherited by the processes launched
+ from the worker, such as external health checks.
+
* HAPROXY_STARTUP_VERSION: contains the version used to start, in master-
worker mode this is the version which was used to start the master, even
after updating the binary and reloading.
- unix-bind
- unsetenv
- user
+ - worker-id
- wurfl-cache-size
- wurfl-data-file
- wurfl-information-list
nodes, it becomes easy to immediately spot what server is handling the
traffic.
+worker-id <id>
+ Replaces the default worker process identifier with <id>. The format rules
+ are identical to the proxy and server "guid" attributes: up to 127 characters
+ containing only alphanumeric values, ".", ":", "-", and "_".
+
+ HAProxy generates a time-ordered UUIDv7 for the worker at boot before parsing
+ the configuration. This default identifier changes on every reload, embedding
+ the process start time to enable chronological sorting of workers in logs for
+ example.
+
+ Using worker-id overwrites this identifier and instantly updates the
+ HAPROXY_WORKER_ID environment variable. Any subsequent configuration
+ directive (e.g. "log-format") will use the replaced value. The directive
+ itself can reference HAPROXY_WORKER_ID before it is overwritten, allowing
+ to combine for example a node name with the generated UUID.
+
+ Example:
+ worker-id "pop7-node1-inst3-${HAPROXY_WORKER_ID}"
+
+ The identifier is exported as the HAPROXY_WORKER_ID environment variable (see
+ section 2.3). See also HAPROXY_MASTER_ID in section 2.3.
+
wurfl-cache-size <size>
Sets the WURFL Useragent cache size. For faster lookups, already processed user
agents are kept in a LRU cache :
char *pidfile;
char *node, *desc; /* node name & description */
char *master_id; /* master process' unique ID, preserved upon reload */
+ char *worker_id; /* worker process' unique ID, renewed upon reload */
int localpeer_cmdline; /* whether or not the commandline "-L" was set */
int fd_hard_limit; /* hard limit on ulimit-n : 0=unset */
struct buffer log_tag; /* name for syslog */
#endif
#include <haproxy/compression.h>
#include <haproxy/global.h>
+#include <haproxy/guid.h>
#include <haproxy/log.h>
#include <haproxy/peers.h>
#include <haproxy/protocol.h>
return 0;
}
+/* Parses the "worker-id" keyword, which assigns a unique identifier to this
+ * worker process. It is preset to a UUID v7 generated at boot (see
+ * init_worker_id()). It is parsed only by the worker and the environment
+ * variable is set on the fly so that its value is instantly known from next
+ * directives making use of "$HAPROXY_WORKER_ID" (e.g. log-format).
+ */
+static int cfg_parse_global_worker_id(char **args, int section_type, struct proxy *curpx,
+ const struct proxy *defpx, const char *file, int line,
+ char **err)
+{
+ char *errmsg = NULL;
+
+ if (too_many_args(1, args, err, NULL))
+ return -1;
+
+ if (*(args[1]) == 0) {
+ memprintf(err, "'%s' expects an identifier as an argument.", args[0]);
+ return -1;
+ }
+
+ if (!guid_is_valid_fmt(args[1], &errmsg)) {
+ memprintf(err, "'%s': %s.", args[0], errmsg);
+ free(errmsg);
+ return -1;
+ }
+
+ if (setenv("HAPROXY_WORKER_ID", args[1], 1) != 0) {
+ memprintf(err, "'%s' failed to set HAPROXY_WORKER_ID to '%s' : %s.\n",
+ args[0], args[1], strerror(errno));
+ return -1;
+ }
+
+ ha_free(&global.worker_id);
+ global.worker_id = strdup(args[1]);
+ if (!global.worker_id) {
+ memprintf(err, "cannot allocate memory for '%s'.", args[0]);
+ return -1;
+ }
+
+ return 0;
+}
+
static struct cfg_kw_list cfg_kws = {ILH, {
{ CFG_GLOBAL, "chroot", cfg_parse_global_chroot },
{ CFG_GLOBAL, "daemon", cfg_parse_global_mode, KWF_DISCOVERY } ,
{ CFG_GLOBAL, "tune.streams-elasticity", cfg_parse_global_tune_opts },
{ CFG_GLOBAL, "tune.takeover-other-tg-connections", cfg_parse_global_tune_opts },
{ CFG_GLOBAL, "unsetenv", cfg_parse_global_env_opts, KWF_DISCOVERY },
+ { CFG_GLOBAL, "worker-id", cfg_parse_global_worker_id },
{ CFG_GLOBAL, "zero-warning", cfg_parse_global_mode, KWF_DISCOVERY },
{ 0, NULL, NULL },
}};
}
}
+/* Assigns a unique ID to the worker process if it does not have one yet, i.e.
+ * if "worker-id" was not found in the configuration, and exports it to the
+ * environment so that it may be referenced as $HAPROXY_WORKER_ID from the
+ * configuration, and be inherited by the processes we fork. A time-ordered
+ * UUID v7 is used so that a newly started worker may be told from the previous
+ * ones, which may still be finishing their work after a reload. This must not
+ * be called in the master, which has its own ID instead, preserved across
+ * reloads (see mworker_prepare_master()).
+ */
+static void init_worker_id(void)
+{
+ if (!global.worker_id) {
+ char uuid[40];
+ struct buffer out = b_make(uuid, sizeof(uuid), 0, 0);
+
+ ha_generate_uuid_v7(&out);
+ global.worker_id = strdup(uuid);
+ if (!global.worker_id) {
+ ha_alert("Cannot allocate memory for the worker's ID.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ setenv("HAPROXY_WORKER_ID", global.worker_id, 1);
+}
+
/*
* This is a second part of the late init (previous init() function). It should
* be called after the stage, when all basic runtime modes (daemon, master-worker)
ha_free(&global.node);
ha_free(&global.desc);
ha_free(&global.master_id);
+ ha_free(&global.worker_id);
ha_free(&oldpids);
ha_free(&old_argv);
ha_free(&localpeer);
*/
setenv("HAPROXY_LOCALPEER", localpeer, 1);
+ /* Let's make sure HAPROXY_WORKER_ID is set as well */
+ init_worker_id();
+
/* nbthread and *thread keywords parsers are sensible to global
* section position, it should be placed as the first in
* the configuration, if these keywords are inside. So, let's