[MINOR] add option "mysql-check" to use MySQL health checks
This patch adds support for MySQL health checks. Those are
enabled using the new option "mysql-check".
diff --git a/doc/configuration.txt b/doc/configuration.txt
index c5dd105..3f07de6 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -771,6 +771,7 @@
[no] option log-separate-
errors X X X -
[no] option logasap X X X -
+option mysql-check X - X X
[no] option nolinger X X X X
option originalto X X X X
[no] option persist X - X X
@@ -2526,8 +2527,8 @@
option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www
server apache1 192.168.1.1:443 check port 80
- See also : "option ssl-hello-chk", "option smtpchk", "http-check" and the
- "check", "port" and "interval" server options.
+ See also : "option ssl-hello-chk", "option smtpchk", "option mysql-check",
+ "http-check" and the "check", "port" and "interval" server options.
option http-server-close
@@ -2770,6 +2771,28 @@
logging.
+option mysql-check
+ Use Mysql health checks for server testing
+ May be used in sections : defaults | frontend | listen | backend
+ yes | no | yes | yes
+ Arguments : none
+
+ The check consists in parsing Mysql Handshake Initialisation packet or Error
+ packet, which is sent by MySQL server on connect. It is a basic but useful
+ test which does not produce any logging on the server. However, it does not
+ check database presence nor database consistency, nor user permission to
+ access. To do this, you can use an external check with xinetd for example.
+
+ Most often, an incoming MySQL server needs to see the client's IP address for
+ various purposes, including IP privilege matching and connection logging.
+ When possible, it is often wise to masquerade the client's IP address when
+ connecting to the server using the "usesrc" argument of the "source" keyword,
+ which requires the cttproxy feature to be compiled in, and the MySQL server
+ to route the client via the machine hosting haproxy.
+
+ See also: "option httpchk"
+
+
option nolinger
no option nolinger
Enable or disable immediate session resource cleaning after close
@@ -4809,8 +4832,8 @@
"port" parameter, the source address using the "source" address, and the
interval and timers using the "inter", "rise" and "fall" parameters. The
request method is define in the backend using the "httpchk", "smtpchk",
- and "ssl-hello-chk" options. Please refer to those options and parameters for
- more information.
+ "mysql-check" and "ssl-hello-chk" options. Please refer to those options and
+ parameters for more information.
Supported in default-server: No
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 2ba298b..a7887e6 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -132,6 +132,8 @@
#define PR_O2_AS_M_QS 0x00010000 /* query-string mode */
#define PR_O2_AS_M_ANY 0x00010000 /* mask covering all PR_O2_AS_M_* values */
+#define PR_O2_MYSQL_CHK 0x00020000 /* use MYSQL check for server health */
+
struct error_snapshot {
struct timeval when; /* date of this event, (tv_sec == 0) means "never" */
unsigned int len; /* original length of the last invalid request/response */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 9781623..7a7af79 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -2227,6 +2227,7 @@
free(curproxy->check_req);
curproxy->options &= ~PR_O_SSL3_CHK;
curproxy->options &= ~PR_O_SMTP_CHK;
+ curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options |= PR_O_HTTP_CHK;
if (!*args[2]) { /* no argument */
curproxy->check_req = strdup(DEF_CHECK_REQ); /* default request */
@@ -2256,6 +2257,7 @@
free(curproxy->check_req);
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options &= ~PR_O_SMTP_CHK;
+ curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options |= PR_O_SSL3_CHK;
}
else if (!strcmp(args[1], "smtpchk")) {
@@ -2263,6 +2265,7 @@
free(curproxy->check_req);
curproxy->options &= ~PR_O_HTTP_CHK;
curproxy->options &= ~PR_O_SSL3_CHK;
+ curproxy->options2 &= ~PR_O2_MYSQL_CHK;
curproxy->options |= PR_O_SMTP_CHK;
if (!*args[2] || !*args[3]) { /* no argument or incomplete EHLO host */
@@ -2282,6 +2285,14 @@
}
}
}
+ else if (!strcmp(args[1], "mysql-check")) {
+ /* use MYSQL request to check servers' health */
+ free(curproxy->check_req);
+ curproxy->options &= ~PR_O_HTTP_CHK;
+ curproxy->options &= ~PR_O_SSL3_CHK;
+ curproxy->options &= ~PR_O_SMTP_CHK;
+ curproxy->options2 |= PR_O2_MYSQL_CHK;
+ }
else if (!strcmp(args[1], "forwardfor")) {
int cur_arg;
diff --git a/src/checks.c b/src/checks.c
index 05cb549..61349fe 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -660,7 +660,8 @@
/* we don't want to mark 'UP' a server on which we detected an error earlier */
if ((s->proxy->options & PR_O_HTTP_CHK) ||
(s->proxy->options & PR_O_SSL3_CHK) ||
- (s->proxy->options & PR_O_SMTP_CHK)) {
+ (s->proxy->options & PR_O_SMTP_CHK) ||
+ (s->proxy->options2 & PR_O2_MYSQL_CHK)) {
int ret;
/* 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.
@@ -862,6 +863,33 @@
else
set_server_check_status(s, HCHK_STATUS_L7STS, desc);
}
+ else if (s->proxy->options2 & PR_O2_MYSQL_CHK) {
+ /* MySQL Error packet always begin with field_count = 0xff
+ * contrary to OK Packet who always begin whith 0x00 */
+ if (trash[4] != -1) {
+ /* We set the MySQL Version in description for information purpose
+ * FIXME : it can be cool to use MySQL Version for other purpose,
+ * like mark as down old MySQL server.
+ */
+ if (len > 51) {
+ desc = ltrim(&trash[5], ' ');
+ set_server_check_status(s, HCHK_STATUS_L7OKD, desc);
+ }
+ else {
+ /* it seems we have a OK packet but without a valid length,
+ * it must be a protocol error
+ */
+ set_server_check_status(s, HCHK_STATUS_L7RSP, trash);
+ }
+ }
+ else {
+ /* An error message is attached in the Error packet,
+ * so we can display it ! :)
+ */
+ desc = ltrim(&trash[7], ' ');
+ set_server_check_status(s, HCHK_STATUS_L7STS, desc);
+ }
+ }
else {
/* other checks are valid if the connection succeeded anyway */
set_server_check_status(s, HCHK_STATUS_L4OK, NULL);
diff --git a/tests/test-sql.cfg b/tests/test-sql.cfg
new file mode 100644
index 0000000..52dfefd
--- /dev/null
+++ b/tests/test-sql.cfg
@@ -0,0 +1,29 @@
+# This is a test configuration.
+# It requires a mysql server running on local port 3306.
+
+global
+ maxconn 500
+
+defaults
+ contimeout 1000
+ clitimeout 5000
+ srvtimeout 5000
+ retries 1
+ option redispatch
+
+listen stats
+ bind :8080
+ mode http
+ stats enable
+ stats uri /stats
+
+listen mysql_1
+ bind :3307
+ mode tcp
+ balance roundrobin
+ option mysql-check
+ server srv1 127.0.0.1:3306 check port 3306 inter 1000 fall 1
+# server srv2 127.0.0.2:3306 check port 3306 inter 1000 fall 1
+# server srv3 127.0.0.3:3306 check port 3306 inter 1000 fall 1
+# server srv4 127.0.0.4:3306 check port 3306 inter 1000 fall 1
+