nginx_tcp_proxy_module对mysql做负载均衡被block的解决办法

上个文章用nginx_tcp_proxy_module 来给mysql 做均衡负载 , 在此模块对mysql 做健康检查时 发送空包 ,被max_connect_errors block 的问题 , 今天简单弄了下 ,让它发送 一个 user=root ,password 为空 的 mysql login packet . 测试了3000多次检查 , 即使登陆不成功 ,也不会被block掉

至于带密码的login packet ,涉及到跟mysql 的握手步骤 ,还有待研究 不过感觉就健康检查没必要真的login 进去 , 而且即使mysql有login 失败的block ,专门给nginx 所在IP 开一个 密码为空的用户也是可以接受的方案

下面是针对nginx_tcp_proxy_module-v0.26 的patch

diff -urN yaoweibin-nginx_tcp_proxy_module-b83e5a6/ngx_tcp_upstream_check.c yaoweibin-nginx_tcp_proxy_module-b83e5a6_new/ngx_tcp_upstream_check.c
--- yaoweibin-nginx_tcp_proxy_module-b83e5a6/ngx_tcp_upstream_check.c   2011-12-30 10:43:33.000000000 +0800
+++ yaoweibin-nginx_tcp_proxy_module-b83e5a6_new/ngx_tcp_upstream_check.c       2012-07-20 14:40:00.888077351 +0800
@@ -77,6 +77,18 @@
        "\x00"                /* Compression Type    : 0x00 = NULL compression   */
 };

+const char mysql_login_pkt[] = {
+       "\x3c\x00\x00"          /* Packet Length ,      :       封包长度 */
+       "\x01"                  /* Packet Number        :       封包序列号 ,login packet 固定为 0x01 */
+       "\x05\xa6"              /* Client Capabilities  :       不懂啥意思 */
+       "\x0f\x00"              /* Extended Client Capabilities :               */
+       "\x00\x00\x00\x01"      /* Max packet           :       =0x01000000 */
+       "\x21"                  /* Character set        :       默认字符集  */
+       "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" /* Unknown */
+       "\x72\x6f\x6f\x74\x00"  /* User Name    :       0x726f6f74 = 'root' ,字符串的 acsii 码 ,'\0'结尾, 长度变化时,上面的 Packet Length 要跟着变      */
+       "\x00"                  /* Password     :       空密码 , */
+       "\x6d\x79\x73\x71\x6c\x5f\x6e\x61\x74\x69\x76\x65\x5f\x70\x61\x73\x73\x77\x6f\x72\x64\x00"      /* 结尾固定字符串 "mysql_native_password" */
+};

 #define HANDSHAKE    0x16
 #define SERVER_HELLO 0x02
@@ -133,7 +145,7 @@
     {
         NGX_TCP_CHECK_MYSQL,
         "mysql",
-        ngx_null_string,
+        ngx_string(mysql_login_pkt),
         0,
         ngx_tcp_check_send_handler,
         ngx_tcp_check_recv_handler,
@@ -1094,6 +1106,9 @@
     ctx->send.start = ctx->send.pos = (u_char *)uscf->send.data;
     ctx->send.end = ctx->send.last = ctx->send.start + uscf->send.len;

+    ngx_log_debug1(NGX_LOG_DEBUG_TCP, ngx_cycle->log, 0,
+            "mysql_init: send:%V", &uscf->send);
+
     ctx->recv.start = ctx->recv.pos = NULL;
     ctx->recv.end = ctx->recv.last = NULL;