]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MINOR] add option "mysql-check" to use MySQL health checks
authorHervé COMMOWICK <hcommowick@exosec.fr>
Tue, 12 Jan 2010 08:25:13 +0000 (09:25 +0100)
committerWilly Tarreau <w@1wt.eu>
Tue, 12 Jan 2010 09:37:39 +0000 (10:37 +0100)
This patch adds support for MySQL health checks. Those are
enabled using the new option "mysql-check".

doc/configuration.txt
include/types/proxy.h
src/cfgparse.c
src/checks.c
tests/test-sql.cfg [new file with mode: 0644]

index c5dd1054becc7abfe4ddf742c405ccb0a6b1fca3..3f07de68caa7cd67a117cc81d9d6dd8c084b64e9 100644 (file)
@@ -771,6 +771,7 @@ option httplog              X          X         X         X
 [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 <method> <uri> <version>
           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 @@ no option logasap
              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 @@ check
   "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
 
index 2ba298b8eed5191907da60b3f85ca763a457e5f6..a7887e6ae47b9ed0e12b3650d5e84744ec748bfa 100644 (file)
 #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 */
index 978162386ee85ceb996ead69b6b3327abef93592..7a7af790c733f2375d747895182bac648aeb7f1c 100644 (file)
@@ -2227,6 +2227,7 @@ stats_error_parsing:
                        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 @@ stats_error_parsing:
                        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 @@ stats_error_parsing:
                        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 @@ stats_error_parsing:
                                }
                        }
                }
+               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;
 
index 05cb54957241bc08de9c290c5846e9d4d66d4f6b..61349fef760e788dd60a0e484492e250ea0ea219 100644 (file)
@@ -660,7 +660,8 @@ static int event_srv_chk_w(int fd)
                /* 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 @@ static int event_srv_chk_r(int fd)
                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 (file)
index 0000000..52dfefd
--- /dev/null
@@ -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
+