Willy,
Thank you for the feedback. I believe that the patch attached at the
bottom of this email incorporates your suggestions. Please let me know
any further steps I need to take.
As for testing, I ran the following test:
=== Test Setup ===
I set up a config, used netcat to create some dummy services, and
looked at what the sent headers looked like. I bound the server to
127.0.0.1 and my http test server backend was at 127.0.0.2.
=== /tmp/haproxy.cfg ===
global
daemon
defaults
timeout connect 200ms
timeout client 1000ms
timeout server 1000ms
mode http
option forceclose
listen stats :3217
mode http
stats enable
stats uri /
stats refresh 1m
stats show-node
frontend test.main
bind 127.0.0.1:16000
default_backend test.main
backend test.main
option httpchk GET /
http-check send-state
server testhttp 127.0.0.2:8001 observe layer7 check
frontend test_socket.main
bind 127.0.0.1:16001
default_backend test_socket.main
backend test_socket.main
option httpchk
http-check send-state
server tstsocket /tmp/test.sock observe layer7 check
=== end /tmp/haproxy.cfg ===
I (re)started haproxy with:
./haproxy -f /tmp/haproxy.cfg -p /tmp/haproxy.pid -sf $(cat /tmp/haproxy.pid)
And than used netcat to create dummy servers at these two addresses:
jlynch@<host>:~$ nc.openbsd -l 127.0.0.2 8001
GET / HTTP/1.0
X-Haproxy-Server-State: DOWN; address=127.0.0.2; port=8001;
name=test.main/testhttp; node=<host>; weight=1/0; scur=0/0; qcur=0
jlynch@<host>:~$ rm /tmp/test.sock; nc.openbsd -lU /tmp/test.sock
OPTIONS / HTTP/1.0
X-Haproxy-Server-State: DOWN; address=unix; port=unix;
name=test_socket.main/tstsocket; node=<host>; weight=1/0; scur=0/0;
qcur=0
=== End Test ===
It appears that the address and port have "unix" for domain sockets,
which is consistent with my understanding of the addr_to_str and
port_to_str methods in src/standard.c . If you like I can inspect the
return value from addr_to_str and try to find the path or some such.
Thank you,
-Joey Lynch
=== Patch ===
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 3ae6624..c8b648b 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -2896,6 +2896,14 @@ http-check send-state
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 "address", containing the address of the backend server.
+ This corresponds to the <address> field in the server declaration. For
+ unix domain sockets, it will read "unix".
+
+ - a variable "port", containing the port of the backend server. This
+ corresponds to the <port> field in the server declaration. For unix
+ domain sockets, it will read "unix".
+
- 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.
diff --git a/src/checks.c b/src/checks.c
index 71debb6..1959c98 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -471,6 +471,8 @@ static int httpchk_build_status_header(struct
server *s, char *buffer, int size)
int sv_state;
int ratio;
int hlen = 0;
+ char addr[46];
+ char port[6];
const char *srv_hlt_st[7] = { "DOWN", "DOWN %d/%d",
"UP %d/%d", "UP",
"NOLB %d/%d", "NOLB",
@@ -501,8 +503,11 @@ static int httpchk_build_status_header(struct
server *s, char *buffer, int size)
(s->state != SRV_ST_STOPPED) ? (s->check.health -
s->check.rise + 1) : (s->check.health),
(s->state != SRV_ST_STOPPED) ? (s->check.fall) :
(s->check.rise));
- hlen += snprintf(buffer + hlen, size - hlen, "; name=%s/%s;
node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
- s->proxy->id, s->id,
+ addr_to_str(&s->addr, addr, sizeof(addr));
+ port_to_str(&s->addr, port, sizeof(port));
+
+ hlen += snprintf(buffer + hlen, size - hlen, "; address=%s;
port=%s; name=%s/%s; node=%s; weight=%d/%d; scur=%d/%d; qcur=%d",
+ addr, port, 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,
On Sat, Jan 31, 2015 at 10:35 PM, Willy Tarreau <[email protected]> wrote:
> Hello Joseph,
>
> I'm CCing Bhaskar since he was the one proposing the first solution, he
> may have some useful insights. Other points below.
>
> On Thu, Jan 15, 2015 at 01:23:59PM -0800, Joseph Lynch wrote:
>> Hello,
>>
>> I am trying to set up a health check service similar to the inetd solutions
>> suggested in the documentation. Unfortunately, my backends run on different
>> ports because they are being created dynamically and as far as I can tell I
>> cannot include the server port in my healthcheck either as part of the
>> server declaration, a header, or as part of the healthcheck uri itself.
>>
>> I have been trying to come up with potential solutions that are not overly
>> invasive, and I think that the simplest solution is to include the server
>> host and port in the existing send-state header. I have included a patch
>> that I believe does this at the end of this email. Before I go off
>> maintaining a local fork, I wanted to ask if the haproxy devs would be
>> sympathetic to me trying to upstream this patch?
>
> I'm personally fine with it. As you say, it's really not invasive, so we
> could merge it and even backport it into 1.5-stable. I'd slightly change
> something however, I'd use "address" instead of "host" in the field, since
> that's what you're copying there. "Host" could be used later to copy the
> equivalent of a host name, so let's not misuse the field name.
>
>> As for prior art, I found a few posts on this mailing list about the
>> ability to add headers to http checks. I believe that something like
>> http://marc.info/?l=haproxy&m=139181606417120&w=2 would be more then what
>> we need to solve this problem, but that thread seems to have died. I do
>> believe that a general ability to add headers to healthchecks would be
>> superior to my patch, but the general solution is significantly harder to
>> pull off.
>
> I'd like to re-heat that thread. I didn't even remember about it, indeed
> we were busy finalizing 1.5. Bhaskar, I still think your work makes sense
> for 1.6, so if you still have your patch, it's probably time to resend it :-)
>
>> If you guys agree that this patch is ok, please let me know what
>> I need to do next. I don't see any tests for the send-state option but I
>> presume that I would need to update the documentation.
>
> Please check what your patch does with servers not having any IP nor port
> (ie: the ones reached over a unix socket). I suspect you'll have the socket
> path in the host part, and "0" as the port, but I'm not sure, so I'd like
> to be certain. Also, please verify that it's really the server's address
> and port, and not the ones from the check, that are passed in the header.
> So if you specify "addr" and "port" on the server line, these ones are only
> used for the check, and we want to be sure that the real ones are properly
> used. Once everything's OK, please update the doc about "send-state".
>
> Thanks,
> Willy