Hello,
I apologize for my persistence and realize that everyone if busy with getting
1.5 out of the door. I have no expectations on that front for the patch included
here. However any feedback is welcome. I went thru some of the submitted
patches and saw one by Simon Horman to use an external process after I
made this change and will revisit that again.
I re-did my implementation, and this time I am submitting it as a patch for
consideration. I am posting the commit message that explains the change.
=================================================================
We add new directives to the http-check keyword
The server option is used to specify an external
health checking server to use for health checks.
Example:
http-check server <ipv4|ipv6>
The info option is used to specify a http
header to communicate information about the server
being checked to the external health checking server
Example:
http-check info [header <http-header>]
The default value of the header is 'X-Check-Info'
This option is independent of the server directive. When
used includes a http header in the health check request
of the form
<http-header>: <value>
Finally, we add to the server directive a 'info'
option. This value assigned to this option is passed
to the external health checking server.
Example:
server id <addr> [info <value>]
Putting it all togeather
backend bck1
mode http
# the host header works but wasn't the intent
option httpchk GET /health HTTP/1.1\r\nHost:\ www.hst1.com
# specify a server to use for the check
http-check server chksrv1.dc.hst1.com
# request for info about the server using the default host header
# the following 2 lines are equivalent
# http-check info
http-check info X-Check-Info
# pass in the info using the default
# the following 2 lines are equivalent
# server a1 a1.dc.hst1.com:80 weight 20 maxconn 5 check inter 2s
server a1 a1.dc.hst1.com:80 weight 20 maxconn 5 check inter 2s info a1
# this is probably a better alternative
server a1 a1.dc.hst1.com:80 weight 20 maxconn 5 check inter 2s
info a1.dc.hst1.com
=================================================================
This implementation can also be used for http health checks when
running in tcp mode
providing a potential alternative to implementing health checks for
tcp mode deployments
not directly available in haproxy, also allowing for more advanced
health check beyond
a hello message.
Following is a config that I used to test this
global
maxconn 10
defaults
mode tcp
clitimeout 30m
srvtimeout 30m
contimeout 4s
backend myblog
option httpchk GET /_health.php HTTP/1.1
http-check server bhaskar-dev:80
http-check info
server b1 blackmagic.tumblr.com:80 weight 20 maxconn 5 check
inter 2s info blackmagic.tumblr.com
frontend myblogfrontend
bind *:9080
default_backend myblog
Thanks
Bhaskar
On Thu, Feb 6, 2014 at 2:45 PM, Bhaskar Maddala <[email protected]> wrote:
> Hello,
>
> Since I did not get any responses on this, I decided to try
> motivating a reponse
> by attempting an implementation. I am attaching a patch that does
> this. Admittedly
> this patch is an iteration and I am not submitting it for anything
> more than receiving
> feedback, on the requirement, alternative ideas and the implementation.
>
> Following is an explanation
>
> I added an option httpchksrv which takes an ipv4/6 address (external
> health checker)
> and an option http header. The http header is used to communicate to the
> health
> check server the backend server to check.
>
> option httpchk GET /_health.php HTTP/1.1
> option httpchksrv <ipv4|ipv6> [header
> <http-header-name=X-Check-For>]
>
> Next, I added a "header-value" specification to the server definition
>
> server a1 magic.tumblr.com:80 weight 20 maxconn 5 check inter
> 2s header-value magic.tumblr.com
>
> the header-value is used for the http-header-name specified in httpchksrv
>
> Here is an example of the health check request
>
> GET /_health.php HTTP/1.1
> X-Check-For: magic.tumblr.com
>
> The default value of header-value is the server id, in this case 'a1'
>
> The following is a little abstract and describes how health checks can be
> cached
> using this change, please bear with my attempts to describe it, these may be
> in-adequate. Please take this for what it is, broad strokes of an
> idea. I am not in any way advocating for this deployment.
>
> Going back to my original motivation "excessive health checks due to
> increasing
> proxy and web application deployment", here is a description of how I can
> solve
> it using this implementation.
>
> On haproxy I define 2 frontend, one on port 80 and one on port 6777. The
> httpchksrv specification is used to direct health checks back to haproxy on
> port
> 6777. With haproxy in http mode
>
> option httpchksrv 127.0.0.1:6777
>
> Each server specification on the backend for port 80 (production traffic) uses
> a server specification as
>
> server a1 server:80 weight 20 maxconn 5 check inter 2s
>
> I define a backend of varnish nodes to use with the front end on port 6777.
> I also make sure that the varnish backend uses only L4 health checks.
>
> Health check are passed to varnish from all the proxies consistently hashed on
> the http header X-Check-For via their front end on port 6777. Varnish
> vcl is used to
> obtain the header value 'X-Check-For' and make a health check request to the
> appropriate web host if required, it may return cached health check
> responses according
> the configured TTL.
>
>
> Thanks
> Bhaskar
>
> On Fri, Jan 31, 2014 at 1:46 PM, Bhaskar Maddala <[email protected]> wrote:
>> Hello,
>>
>> As the number of haproxy deployments (>20) grows in our infrastructure
>> along
>> with an increase in the number of backends ~1500 we are beginning to
>> see a non trivial resources allocated to health checks. Each proxy instance
>> health checking each backend every 2 seconds.
>>
>> In an earlier conversation with Willy I was directed to look into the
>> options
>> fastinter and on-error configuration options. I have done this but wanted to
>> speak about how others might have addressed this and if there was any
>> interest in implementing something along these lines and gather
>> ideas/comments
>> on what such an implementation would look like.
>>
>> We use haproxy as a http load balancer and I have not given any thought
>> about how the following description applies to tcp mode.
>>
>> Currently we http check our backends using
>>
>> option httpchk GET /_check.php HTTP/1.1\r\nHost:\ www.domain.com
>>
>> We were considering adding an additional directive to specify a check
>> server
>> in addition to the httpchk directive
>>
>> option httpchk GET /_health.php HTTP/1.1\r\nHost:\ hdr(Host)
>> option chksrv server hcm-008dad0f 172.16.114.52:80
>>
>> The change would add a dynamic field to the health check request.
>> hdr(Host) (http host header in this instance) is the field used to
>> communicate
>> the server to be health checked to the external check server.
>>
>> The check server can/will be implemented to cache health check responses from
>> the back ends.
>>
>> One of the justifications for implementing this is the need in my
>> environment to take
>> into consideration factors not available to the backends when
>> responding to a health
>> check. As an example we will be implementing in our check server
>> ability to force
>> success/failure of health checks on groups of backends related in some
>> manner.
>> We expect this to allow us to avoid brown out scenarios we have
>> encountered in the past.
>>
>> Has anyone considered/achieved something along these lines, or have
>> suggestions
>> on how we could implement the same?
>>
>> Thanks
>> Bhaskar
From 434317d54ad36e62560454eb0a0f6f43be17b091 Mon Sep 17 00:00:00 2001
From: Bhaskar Maddala <[email protected]>
Date: Fri, 7 Feb 2014 13:55:35 -0500
Subject: [PATCH] Add ability to externalize health check
Summary:
We add new directives to the http-check keyword
The server option is used to specify an external
health checking server to use for health checks.
Example:
http-check server <ipv4|ipv6>
The info option is used to specify a http
header to communicate information about the server
being checked to the external health checking server
Example:
http-check info [header <http-header>]
The default value of the header is 'X-Check-Info'
This option is independent of the server directive. When
used includes a http header in the health check request
of the form
<http-header>: <value>
Finally, we add to the server directive a 'info'
option. This value assigned to this option is passed
to the external health checking server.
Example:
server id <addr> [info <value>]
Putting it all togeather
backend bck1
mode http
# the host header works but wasn't the intent
option httpchk GET /health HTTP/1.1\r\nHost:\ www.hst1.com
# specify a server to use for the check
http-check server chksrv1.dc.hst1.com
# request for info about the server using the default host header
# the following 2 lines are equivalent
# http-check info
http-check info X-Check-Info
# pass in the info using the default
# the following 2 lines are equivalent
# server a1 a1.dc.hst1.com:80 weight 20 maxconn 5 check inter 2s
server a1 a1.dc.hst1.com:80 weight 20 maxconn 5 check inter 2s info a1
# this is probably a better alternative
server a1 a1.dc.hst1.com:80 weight 20 maxconn 5 check inter 2s info
a1.dc.hst1.com
---
include/common/defaults.h | 2 +
include/types/proxy.h | 8 +++-
include/types/server.h | 3 ++
src/cfgparse.c | 110 ++++++++++++++++++++++++++++++++++++++-------
src/checks.c | 112 +++++++++++++++++++++++++++-------------------
5 files changed, 169 insertions(+), 66 deletions(-)
diff --git a/include/common/defaults.h b/include/common/defaults.h
index f765e90..17bc5d2 100644
--- a/include/common/defaults.h
+++ b/include/common/defaults.h
@@ -131,6 +131,8 @@
#define DEF_SMTP_CHECK_REQ "HELO localhost\r\n"
#define DEF_LDAP_CHECK_REQ
"\x30\x0c\x02\x01\x01\x60\x07\x02\x01\x03\x04\x00\x80\x00"
#define DEF_REDIS_CHECK_REQ "*1\r\n$4\r\nPING\r\n"
+#define DEF_CHECK_HOST_HDR "X-Check-Info"
+#define DEF_CHECK_HOST_PORT 80
#define DEF_HANA_ONERR HANA_ONERR_FAILCHK
#define DEF_HANA_ERRLIMIT 10
diff --git a/include/types/proxy.h b/include/types/proxy.h
index af2a3ab..638b5f7 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -142,7 +142,8 @@ enum pr_mode {
#define PR_O2_SRC_ADDR 0x00100000 /* get the source ip and port for logs
*/
#define PR_O2_FAKE_KA 0x00200000 /* pretend we do keep-alive with
server eventhough we close */
-/* unused: 0x00400000 */
+#define PR_O2_CHK_INFO 0x00400000 /* include info header and
value in http health checks */
+
#define PR_O2_EXP_NONE 0x00000000 /* http-check : no expect rule */
#define PR_O2_EXP_STS 0x00800000 /* http-check expect status */
#define PR_O2_EXP_RSTS 0x01000000 /* http-check expect rstatus */
@@ -338,7 +339,10 @@ struct proxy {
int grace; /* grace time after stop
request */
struct list tcpcheck_rules; /* tcp-check send / expect
rules */
char *check_req; /* HTTP or SSL request to use
for PR_O_HTTP_CHK|PR_O_SSL3_CHK */
- int check_len; /* Length of the HTTP or SSL3
request */
+ int check_req_len; /* Length of the HTTP or SSL3
request */
+ struct sockaddr_storage check_addr; /* the address to check */
+ char *check_for_hdr_name; /* HTTP header used to
identify host being checked */
+ int check_for_hdr_name_len; /* Length of the HTTP
header */
char *expect_str; /* http-check expected content
: string or text version of the regex */
regex_t *expect_regex; /* http-check expected content
*/
struct chunk errmsg[HTTP_ERR_SIZE]; /* default or customized error
messages for known errors */
diff --git a/include/types/server.h b/include/types/server.h
index 54ab813..ef56a49 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -161,6 +161,9 @@ struct server {
struct sockaddr_storage addr; /* the address to check, if
different from <addr> */
} check_common;
+ char *check_for_hdr_val; /* http header value used
for health checkes */
+ int check_for_hdr_val_len; /* length of the http
header value */
+
struct check check; /* health-check specific
configuration */
struct check agent; /* agent specific configuration
*/
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9993c61..7e56df8 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1841,12 +1841,19 @@ int cfg_parse_listen(const char *file, int linenum,
char **args, int kwm)
if (curproxy->cap & PR_CAP_BE) {
curproxy->fullconn = defproxy.fullconn;
curproxy->conn_retries = defproxy.conn_retries;
+ curproxy->check_addr = defproxy.check_addr;
if (defproxy.check_req) {
- curproxy->check_req = calloc(1,
defproxy.check_len);
- memcpy(curproxy->check_req, defproxy.check_req,
defproxy.check_len);
+ curproxy->check_req = calloc(1,
defproxy.check_req_len);
+ memcpy(curproxy->check_req, defproxy.check_req,
defproxy.check_req_len);
}
- curproxy->check_len = defproxy.check_len;
+ curproxy->check_req_len = defproxy.check_req_len;
+
+ if (defproxy.check_for_hdr_name) {
+ curproxy->check_for_hdr_name = calloc(1,
defproxy.check_for_hdr_name_len);
+ memcpy(curproxy->check_for_hdr_name,
defproxy.check_for_hdr_name, defproxy.check_for_hdr_name_len);
+ }
+ curproxy->check_for_hdr_name_len =
defproxy.check_for_hdr_name_len;
if (defproxy.expect_str) {
curproxy->expect_str =
strdup(defproxy.expect_str);
@@ -1990,6 +1997,8 @@ int cfg_parse_listen(const char *file, int linenum, char
**args, int kwm)
free(defproxy.monitor_uri);
free(defproxy.defbe.name);
free(defproxy.conn_src.iface_name);
+ free(defproxy.check_for_hdr_name);
+ defproxy.check_for_hdr_name_len = 0;
free(defproxy.fwdfor_hdr_name);
defproxy.fwdfor_hdr_len = 0;
free(defproxy.orgto_hdr_name);
@@ -3631,11 +3640,11 @@ stats_error_parsing:
curproxy->options2 |= PR_O2_HTTP_CHK;
if (!*args[2]) { /* no argument */
curproxy->check_req = strdup(DEF_CHECK_REQ); /*
default request */
- curproxy->check_len = strlen(DEF_CHECK_REQ);
+ curproxy->check_req_len = strlen(DEF_CHECK_REQ);
} else if (!*args[3]) { /* one argument : URI */
int reqlen = strlen(args[2]) + strlen("OPTIONS
HTTP/1.0\r\n") + 1;
curproxy->check_req = (char *)malloc(reqlen);
- curproxy->check_len =
snprintf(curproxy->check_req, reqlen,
+ curproxy->check_req_len =
snprintf(curproxy->check_req, reqlen,
"OPTIONS %s
HTTP/1.0\r\n", args[2]); /* URI to use */
} else { /* more arguments : METHOD URI [HTTP_VER] */
int reqlen = strlen(args[2]) + strlen(args[3])
+ 3 + strlen("\r\n");
@@ -3645,7 +3654,7 @@ stats_error_parsing:
reqlen += strlen("HTTP/1.0");
curproxy->check_req = (char *)malloc(reqlen);
- curproxy->check_len =
snprintf(curproxy->check_req, reqlen,
+ curproxy->check_req_len =
snprintf(curproxy->check_req, reqlen,
"%s %s %s\r\n",
args[2], args[3], *args[4]?args[4]:"HTTP/1.0");
}
}
@@ -3668,18 +3677,18 @@ stats_error_parsing:
if (!*args[2] || !*args[3]) { /* no argument or
incomplete EHLO host */
curproxy->check_req =
strdup(DEF_SMTP_CHECK_REQ); /* default request */
- curproxy->check_len =
strlen(DEF_SMTP_CHECK_REQ);
+ curproxy->check_req_len =
strlen(DEF_SMTP_CHECK_REQ);
} else { /* ESMTP EHLO, or SMTP HELO, and a hostname */
if (!strcmp(args[2], "EHLO") ||
!strcmp(args[2], "HELO")) {
int reqlen = strlen(args[2]) +
strlen(args[3]) + strlen(" \r\n") + 1;
curproxy->check_req = (char
*)malloc(reqlen);
- curproxy->check_len =
snprintf(curproxy->check_req, reqlen,
+ curproxy->check_req_len =
snprintf(curproxy->check_req, reqlen,
"%s
%s\r\n", args[2], args[3]); /* HELO hostname */
} else {
/* this just hits the default for now,
but you could potentially expand it to allow for other stuff
though, it's unlikely you'd want to
send anything other than an EHLO or HELO */
curproxy->check_req =
strdup(DEF_SMTP_CHECK_REQ); /* default request */
- curproxy->check_len =
strlen(DEF_SMTP_CHECK_REQ);
+ curproxy->check_req_len =
strlen(DEF_SMTP_CHECK_REQ);
}
}
}
@@ -3726,7 +3735,7 @@ stats_error_parsing:
free(curproxy->check_req);
curproxy->check_req = packet;
- curproxy->check_len =
packet_len;
+ curproxy->check_req_len =
packet_len;
packet_len = htonl(packet_len);
memcpy(packet, &packet_len, 4);
@@ -3754,7 +3763,7 @@ stats_error_parsing:
curproxy->check_req = (char *)
malloc(sizeof(DEF_REDIS_CHECK_REQ) - 1);
memcpy(curproxy->check_req, DEF_REDIS_CHECK_REQ,
sizeof(DEF_REDIS_CHECK_REQ) - 1);
- curproxy->check_len = sizeof(DEF_REDIS_CHECK_REQ) - 1;
+ curproxy->check_req_len = sizeof(DEF_REDIS_CHECK_REQ) -
1;
}
else if (!strcmp(args[1], "mysql-check")) {
@@ -3803,7 +3812,7 @@ stats_error_parsing:
free(curproxy->check_req);
curproxy->check_req = (char
*)calloc(1, reqlen);
- curproxy->check_len = reqlen;
+ curproxy->check_req_len =
reqlen;
snprintf(curproxy->check_req,
4, "%c%c%c",
((unsigned char)
packetlen & 0xff),
@@ -3836,7 +3845,7 @@ stats_error_parsing:
curproxy->check_req = (char *)
malloc(sizeof(DEF_LDAP_CHECK_REQ) - 1);
memcpy(curproxy->check_req, DEF_LDAP_CHECK_REQ,
sizeof(DEF_LDAP_CHECK_REQ) - 1);
- curproxy->check_len = sizeof(DEF_LDAP_CHECK_REQ) - 1;
+ curproxy->check_req_len = sizeof(DEF_LDAP_CHECK_REQ) -
1;
}
else if (!strcmp(args[1], "tcp-check")) {
/* use raw TCPCHK send/expect to check servers' health
*/
@@ -4079,8 +4088,67 @@ stats_error_parsing:
goto out;
}
}
+ else if (!strcmp(args[1], "server")) {
+ if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum,
args[1], NULL))
+ err_code |= ERR_WARN;
+
+ /* use a external http check server instead of querying
the server for health checks */
+ if (!*args[2]) {
+ Alert("parsing [%s:%d]: '%s' expects an
<ipv4|ipv6> address.\n",
+ file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ struct sockaddr_storage *sk;
+ int port1, port2;
+ struct protocol *proto;
+
+ sk = str2sa_range(args[2], &port1, &port2, &errmsg,
NULL);
+ if (!sk) {
+ Alert("parsing [%s:%d] : '%s' : %s\n",
+ file, linenum, args[2], errmsg);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ proto = protocol_by_family(sk->ss_family);
+ if (!proto || !proto->connect) {
+ Alert("parsing [%s:%d] : '%s %s' : connect()
not supported for this address family.\n",
+ file, linenum, args[1], args[2]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (port1 != port2) {
+ Alert("parsing [%s:%d] : '%s' : port ranges and
offsets are not allowed in '%s'\n",
+ file, linenum, args[1], args[2]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+
+ if (!port1)
+ set_host_port(sk, DEF_CHECK_HOST_PORT);
+
+ curproxy->check_addr = *sk;
+ }
+ else if (!strcmp(args[1], "info")) {
+ curproxy->options2 |= PR_O2_CHK_INFO;
+ if (!*args[2]) { /* no argument */
+ curproxy->check_for_hdr_name =
strdup(DEF_CHECK_HOST_HDR);
+ curproxy->check_for_hdr_name_len =
strlen(DEF_CHECK_HOST_HDR);
+ } else if (*args[2] && !strcmp(args[2], "header")) {
+ curproxy->check_for_hdr_name = strdup(args[3]);
+ curproxy->check_for_hdr_name_len =
strlen(args[3]);
+ } else {
+ Alert("parsing [%s:%d] : '%s' : expect valid
http header it can be specified using 'header'\n",
+ file, linenum, args[1]);
+ err_code |= ERR_ALERT | ERR_FATAL;
+ goto out;
+ }
+ }
else {
- Alert("parsing [%s:%d] : '%s' only supports
'disable-on-404', 'send-state', 'expect'.\n", file, linenum, args[0]);
+ Alert("parsing [%s:%d] : '%s' only supports
'disable-on-404', 'send-state', 'expect', 'server', 'info'.\n", file, linenum,
args[0]);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
@@ -4563,6 +4631,8 @@ stats_error_parsing:
newsrv->state = SRV_RUNNING; /* early server setup */
newsrv->last_change = now.tv_sec;
newsrv->id = strdup(args[1]);
+ newsrv->check_for_hdr_val = strdup(args[1]);
+ newsrv->check_for_hdr_val_len = strlen(args[1]);
/* several ways to check the port component :
* - IP => port=+0, relative (IPv4 only)
@@ -4812,6 +4882,11 @@ stats_error_parsing:
newsrv->check_common.addr = *sk;
cur_arg += 2;
}
+ else if (!strcmp(args[cur_arg], "info")) {
+ newsrv->check_for_hdr_val = strdup(args[cur_arg
+ 1]);
+ newsrv->check_for_hdr_val_len =
strlen(args[cur_arg + 1]);
+ cur_arg += 2;
+ }
else if (!strcmp(args[cur_arg], "port")) {
newsrv->check.port = atol(args[cur_arg + 1]);
cur_arg += 2;
@@ -5258,6 +5333,7 @@ stats_error_parsing:
#endif
newsrv->check.send_proxy |= (newsrv->state &
SRV_SEND_PROXY);
}
+
/* try to get the port from check_core.addr if
check.port not set */
if (!newsrv->check.port)
newsrv->check.port =
get_host_port(&newsrv->check_common.addr);
@@ -7078,9 +7154,9 @@ out_uri_auth_compat:
}
if ((curproxy->options2 & PR_O2_CHK_ANY) == PR_O2_SSL3_CHK) {
- curproxy->check_len = sizeof(sslv3_client_hello_pkt) -
1;
- curproxy->check_req = (char
*)malloc(curproxy->check_len);
- memcpy(curproxy->check_req, sslv3_client_hello_pkt,
curproxy->check_len);
+ curproxy->check_req_len =
sizeof(sslv3_client_hello_pkt) - 1;
+ curproxy->check_req = (char
*)malloc(curproxy->check_req_len);
+ memcpy(curproxy->check_req, sslv3_client_hello_pkt,
curproxy->check_req_len);
}
/* ensure that cookie capture length is not too large */
diff --git a/src/checks.c b/src/checks.c
index c3051aa..c559307 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -733,58 +733,65 @@ void __health_adjust(struct server *s, short status)
}
}
-static int httpchk_build_status_header(struct server *s, char *buffer)
+static int httpchk_build_headers(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" };
+ int hlen = 0;
- memcpy(buffer + hlen, "X-Haproxy-Server-State: ", 24);
- hlen += 24;
+ if (s->proxy->options2 & PR_O2_CHK_INFO) {
+ hlen += s->proxy->check_for_hdr_name_len + strlen(": ") +
s->check_for_hdr_val_len + strlen("\r\n");
+ sprintf(buffer, "%s: %s\r\n", s->proxy->check_for_hdr_name,
s->check_for_hdr_val);
+ }
- if (!(s->check.state & CHK_ST_ENABLED))
- sv_state = 6;
- else if (s->state & SRV_RUNNING) {
- if (s->check.health == s->check.rise + s->check.fall - 1)
- sv_state = 3; /* UP */
- else
- sv_state = 2; /* going down */
+ if (s->proxy->options2 & PR_O2_CHK_SNDST) {
+ memcpy(buffer + hlen, "X-Haproxy-Server-State: ", 24);
+ hlen += 24;
- if (s->state & SRV_GOINGDOWN)
- sv_state += 2;
- } else {
- if (s->check.health)
- sv_state = 1; /* going up */
- else
- sv_state = 0; /* DOWN */
- }
+ if (!(s->check.state & CHK_ST_ENABLED))
+ sv_state = 6;
+ else if (s->state & SRV_RUNNING) {
+ if (s->check.health == s->check.rise + s->check.fall -
1)
+ sv_state = 3; /* UP */
+ else
+ sv_state = 2; /* going down */
- hlen += sprintf(buffer + hlen,
- srv_hlt_st[sv_state],
- (s->state & SRV_RUNNING) ? (s->check.health -
s->check.rise + 1) : (s->check.health),
- (s->state & SRV_RUNNING) ? (s->check.fall) :
(s->check.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);
- }
+ if (s->state & SRV_GOINGDOWN)
+ sv_state += 2;
+ } else {
+ if (s->check.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->check.health - s->check.rise + 1) : (s->check.health),
+ (s->state & SRV_RUNNING) ? (s->check.fall)
: (s->check.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';
+ buffer[hlen++] = '\r';
+ buffer[hlen++] = '\n';
+ }
return hlen;
}
@@ -1254,7 +1261,7 @@ static void event_srv_chk_r(struct connection *conn)
if (!done && check->bi->i < 5)
goto wait_more_data;
- if (s->proxy->check_len == 0) { // old mode
+ if (s->proxy->check_req_len == 0) { // old mode
if (*(check->bi->data + 4) != '\xff') {
/* We set the MySQL Version in description for
information purpose
* FIXME : it can be cool to use MySQL Version
for other purpose,
@@ -1505,6 +1512,7 @@ static struct task *process_chk(struct task *t)
int rv;
int ret;
int expired = tick_is_expired(t->expire, now_ms);
+ int hlen = 0;
if (!(check->state & CHK_ST_INPROGRESS)) {
/* no check currently running */
@@ -1539,7 +1547,7 @@ static struct task *process_chk(struct task *t)
* its own strings.
*/
if (check->type && check->type != PR_O2_TCPCHK_CHK &&
!(check->state & CHK_ST_AGENT)) {
- bo_putblk(check->bo, s->proxy->check_req,
s->proxy->check_len);
+ bo_putblk(check->bo, s->proxy->check_req,
s->proxy->check_req_len);
/* we want to check if this host replies to HTTP or
SSLv3 requests
* so we'll send the request, and won't wake the
checker up now.
@@ -1550,8 +1558,13 @@ static struct task *process_chk(struct task *t)
memcpy(check->bo->data + 11, &gmt_time, 4);
}
else if ((check->type) == PR_O2_HTTP_CHK) {
- if (s->proxy->options2 & PR_O2_CHK_SNDST)
- bo_putblk(check->bo, trash.str,
httpchk_build_status_header(s, trash.str));
+
+ /* set up the http request with headers
correctly */
+ hlen = httpchk_build_headers(s, trash.str);
+
+ if (hlen)
+ bo_putblk(check->bo, trash.str, hlen);
+
bo_putstr(check->bo, "\r\n");
*check->bo->p = '\0'; /* to make gdb output
easier to read */
}
@@ -1569,9 +1582,14 @@ static struct task *process_chk(struct task *t)
if (is_addr(&s->check_common.addr))
/* we'll connect to the check addr specified on the
server */
conn->addr.to = s->check_common.addr;
- else
- /* we'll connect to the addr on the server */
- conn->addr.to = s->addr;
+ else {
+ if ((check->type) == PR_O2_HTTP_CHK &&
is_addr(&s->proxy->check_addr))
+ /* we will connect to the check addr specified
on the proxy, only http checks*/
+ conn->addr.to = s->proxy->check_addr;
+ else
+ /* we'll connect to the addr on the server */
+ conn->addr.to = s->addr;
+ }
if (check->port) {
set_host_port(&conn->addr.to, check->port);
--
1.8.3.4 (Apple Git-47)