mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
[MEDIUM] checks: add the server's status in the checks
Now a server can check the contents of the header X-Haproxy-Server-State to know how haproxy sees it. The same values as those reported in the stats are provided : - up/down status + check counts - throttle - weight vs backend weight - active sessions vs backend sessions - queue length - haproxy node name
This commit is contained in:
parent
91caa6fe50
commit
db214364d0
@ -1711,6 +1711,49 @@ http-check disable-on-404
|
|||||||
See also : "option httpchk"
|
See also : "option httpchk"
|
||||||
|
|
||||||
|
|
||||||
|
http-check send-state
|
||||||
|
Enable emission of a state header with HTTP health checks
|
||||||
|
May be used in sections : defaults | frontend | listen | backend
|
||||||
|
yes | no | yes | yes
|
||||||
|
Arguments : none
|
||||||
|
|
||||||
|
When this option is set, haproxy will systematically send a special header
|
||||||
|
"X-Haproxy-Server-State" with a list of parameters indicating to each server
|
||||||
|
how they are seen by haproxy. This can be used for instance when a server is
|
||||||
|
manipulated without access to haproxy and the operator needs to know whether
|
||||||
|
haproxy still sees it up or not, or if the server is the last one in a farm.
|
||||||
|
|
||||||
|
The header is composed of fields delimited by semi-colons, the first of which
|
||||||
|
is a word ("UP", "DOWN", "NOLB"), possibly followed by a number of valid
|
||||||
|
checks on the total number before transition, just as appears in the stats
|
||||||
|
interface. Next headers are in the form "<variable>=<value>", indicating in
|
||||||
|
no specific order some values available in the stats interface :
|
||||||
|
- a variable "name", containing the name of the backend followed by a slash
|
||||||
|
("/") then the name of the server. This can be used when a server is
|
||||||
|
checked in multiple backends.
|
||||||
|
|
||||||
|
- a variable "node" containing the name of the haproxy node, as set in the
|
||||||
|
global "node" variable, otherwise the system's hostname if unspecified.
|
||||||
|
|
||||||
|
- a variable "weight" indicating the weight of the server, a slash ("/")
|
||||||
|
and the total weight of the farm (just counting usable servers). This
|
||||||
|
helps to know if other servers are available to handle the load when this
|
||||||
|
one fails.
|
||||||
|
|
||||||
|
- a variable "scur" indicating the current number of concurrent connections
|
||||||
|
on the server, followed by a slash ("/") then the total number of
|
||||||
|
connections on all servers of the same backend.
|
||||||
|
|
||||||
|
- a variable "qcur" indicating the current number of requests in the
|
||||||
|
server's queue.
|
||||||
|
|
||||||
|
Example of a header received by the application server :
|
||||||
|
>>> X-Haproxy-Server-State: UP 2/3; name=bck/srv2; node=lb1; weight=1/2; \
|
||||||
|
scur=13/22; qcur=0
|
||||||
|
|
||||||
|
See also : "option httpchk", "http-check disable-on-404"
|
||||||
|
|
||||||
|
|
||||||
id <value>
|
id <value>
|
||||||
Set a persistent value for proxy ID. Must be unique and larger than 1000, as
|
Set a persistent value for proxy ID. Must be unique and larger than 1000, as
|
||||||
smaller values are reserved for auto-assigned ids.
|
smaller values are reserved for auto-assigned ids.
|
||||||
|
@ -121,6 +121,9 @@
|
|||||||
#define PR_O2_INDEPSTR 0x00001000 /* independant streams, don't update rex on write */
|
#define PR_O2_INDEPSTR 0x00001000 /* independant streams, don't update rex on write */
|
||||||
/* 0x2000 used in 1.4 */
|
/* 0x2000 used in 1.4 */
|
||||||
#define PR_O2_AS_REQL 0x00004000 /* appsession: learn the session id from the request */
|
#define PR_O2_AS_REQL 0x00004000 /* appsession: learn the session id from the request */
|
||||||
|
/* 0x8000 to 0x40000 used in 1.4 */
|
||||||
|
#define PR_O2_CHK_SNDST 0x00080000 /* send the state of each server along with HTTP health checks */
|
||||||
|
/* end of proxy->options2 */
|
||||||
|
|
||||||
/* This structure is used to apply fast weighted round robin on a server group */
|
/* This structure is used to apply fast weighted round robin on a server group */
|
||||||
struct fwrr_group {
|
struct fwrr_group {
|
||||||
|
@ -2198,6 +2198,10 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int inv)
|
|||||||
/* enable a graceful server shutdown on an HTTP 404 response */
|
/* enable a graceful server shutdown on an HTTP 404 response */
|
||||||
curproxy->options |= PR_O_DISABLE404;
|
curproxy->options |= PR_O_DISABLE404;
|
||||||
}
|
}
|
||||||
|
else if (strcmp(args[1], "send-state") == 0) {
|
||||||
|
/* enable emission of the apparent state of a server in HTTP checks */
|
||||||
|
curproxy->options2 |= PR_O2_CHK_SNDST;
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
|
Alert("parsing [%s:%d] : '%s' only supports 'disable-on-404'.\n", file, linenum, args[0]);
|
||||||
err_code |= ERR_ALERT | ERR_FATAL;
|
err_code |= ERR_ALERT | ERR_FATAL;
|
||||||
@ -4000,6 +4004,13 @@ int check_config_validity()
|
|||||||
err_code |= ERR_WARN;
|
err_code |= ERR_WARN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((curproxy->options2 & PR_O2_CHK_SNDST) && !(curproxy->options & PR_O_HTTP_CHK)) {
|
||||||
|
curproxy->options &= ~PR_O2_CHK_SNDST;
|
||||||
|
Warning("config : '%s' will be ignored for %s '%s' (requires 'option httpchk').\n",
|
||||||
|
"send-state", proxy_type_str(curproxy), curproxy->id);
|
||||||
|
err_code |= ERR_WARN;
|
||||||
|
}
|
||||||
|
|
||||||
/* if a default backend was specified, let's find it */
|
/* if a default backend was specified, let's find it */
|
||||||
if (curproxy->defbe.name) {
|
if (curproxy->defbe.name) {
|
||||||
struct proxy *target;
|
struct proxy *target;
|
||||||
@ -4268,7 +4279,7 @@ int check_config_validity()
|
|||||||
if (curproxy != px &&
|
if (curproxy != px &&
|
||||||
(curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
|
(curproxy->options & PR_O_DISABLE404) != (px->options & PR_O_DISABLE404)) {
|
||||||
Alert("config : %s '%s', server '%s': unable to use %s/%s for"
|
Alert("config : %s '%s', server '%s': unable to use %s/%s for"
|
||||||
"tracing: disable-on-404 option inconsistency.\n",
|
"tracking: disable-on-404 option inconsistency.\n",
|
||||||
proxy_type_str(curproxy), curproxy->id,
|
proxy_type_str(curproxy), curproxy->id,
|
||||||
newsrv->id, px->id, srv->id);
|
newsrv->id, px->id, srv->id);
|
||||||
cfgerr++;
|
cfgerr++;
|
||||||
|
60
src/checks.c
60
src/checks.c
@ -324,6 +324,62 @@ static void set_server_enabled(struct server *s) {
|
|||||||
set_server_enabled(srv);
|
set_server_enabled(srv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int httpchk_build_status_header(struct server *s, char *buffer)
|
||||||
|
{
|
||||||
|
int sv_state;
|
||||||
|
int ratio;
|
||||||
|
int hlen = 0;
|
||||||
|
const char *srv_hlt_st[7] = { "DOWN", "DOWN %d/%d",
|
||||||
|
"UP %d/%d", "UP",
|
||||||
|
"NOLB %d/%d", "NOLB",
|
||||||
|
"no check" };
|
||||||
|
|
||||||
|
memcpy(buffer + hlen, "X-Haproxy-Server-State: ", 24);
|
||||||
|
hlen += 24;
|
||||||
|
|
||||||
|
if (!(s->state & SRV_CHECKED))
|
||||||
|
sv_state = 6; /* should obviously never happen */
|
||||||
|
else if (s->state & SRV_RUNNING) {
|
||||||
|
if (s->health == s->rise + s->fall - 1)
|
||||||
|
sv_state = 3; /* UP */
|
||||||
|
else
|
||||||
|
sv_state = 2; /* going down */
|
||||||
|
|
||||||
|
if (s->state & SRV_GOINGDOWN)
|
||||||
|
sv_state += 2;
|
||||||
|
} else {
|
||||||
|
if (s->health)
|
||||||
|
sv_state = 1; /* going up */
|
||||||
|
else
|
||||||
|
sv_state = 0; /* DOWN */
|
||||||
|
}
|
||||||
|
|
||||||
|
hlen += sprintf(buffer + hlen,
|
||||||
|
srv_hlt_st[sv_state],
|
||||||
|
(s->state & SRV_RUNNING) ? (s->health - s->rise + 1) : (s->health),
|
||||||
|
(s->state & SRV_RUNNING) ? (s->fall) : (s->rise));
|
||||||
|
|
||||||
|
hlen += sprintf(buffer + hlen, "; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
|
||||||
|
s->proxy->id, s->id,
|
||||||
|
global.node,
|
||||||
|
(s->eweight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
|
||||||
|
(s->proxy->lbprm.tot_weight * s->proxy->lbprm.wmult + s->proxy->lbprm.wdiv - 1) / s->proxy->lbprm.wdiv,
|
||||||
|
s->cur_sess, s->proxy->beconn - s->proxy->nbpend,
|
||||||
|
s->nbpend);
|
||||||
|
|
||||||
|
if ((s->state & SRV_WARMINGUP) &&
|
||||||
|
now.tv_sec < s->last_change + s->slowstart &&
|
||||||
|
now.tv_sec >= s->last_change) {
|
||||||
|
ratio = MAX(1, 100 * (now.tv_sec - s->last_change) / s->slowstart);
|
||||||
|
hlen += sprintf(buffer + hlen, "; throttle=%d%%", ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer[hlen++] = '\r';
|
||||||
|
buffer[hlen++] = '\n';
|
||||||
|
|
||||||
|
return hlen;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is used only for server health-checks. It handles
|
* This function is used only for server health-checks. It handles
|
||||||
* the connection acknowledgement. If the proxy requires HTTP health-checks,
|
* the connection acknowledgement. If the proxy requires HTTP health-checks,
|
||||||
@ -363,6 +419,10 @@ static int event_srv_chk_w(int fd)
|
|||||||
}
|
}
|
||||||
else if (s->proxy->options & PR_O_HTTP_CHK) {
|
else if (s->proxy->options & PR_O_HTTP_CHK) {
|
||||||
memcpy(trash, check_req, check_len);
|
memcpy(trash, check_req, check_len);
|
||||||
|
|
||||||
|
if (s->proxy->options2 & PR_O2_CHK_SNDST)
|
||||||
|
check_len += httpchk_build_status_header(s, trash + check_len);
|
||||||
|
|
||||||
trash[check_len++] = '\r';
|
trash[check_len++] = '\r';
|
||||||
trash[check_len++] = '\n';
|
trash[check_len++] = '\n';
|
||||||
trash[check_len] = '\0';
|
trash[check_len] = '\0';
|
||||||
|
Loading…
Reference in New Issue
Block a user