A-A+

利用NetScaler和自行编写的健康检查脚本,完美解决多台MySQL Slave数据库的负载均衡

2008年11月29日 未分类 暂无评论 阅读 1 次
Citrix NetScaler是一款不错的4-7层硬件负载均衡交换机,市场占有率仅次于F5 BIG-IP,位居第二。NetScaler 8.0美国思杰系统有限公司Citrix Systems, Inc)正式推出的最新版本NetScaler产品系列。

  从我的实际测试来看,NetScaler 8.0在七层负载均衡方面,性能和功能都要比F5 BIG-IP强。

NetScaler 8.0的负载均衡监控中,可以对MySQL数据库进行健康检查,而F5 BIG-IP目前只支持对OracleMicrosoft SQL Server数据库的健康检查。

  但是,NetScaler 8.0自带的MySQL健康检查脚本(nsmysql.pl)并不完善,它只能检查一条SQL语句执行是否出错,并不能检查MySQL主从结构中的MySQL Slave数据库同步是否正常、表有无损坏、同步延迟是否过大、是否出现错误、非sleeping状态的连程数是否过高等情况。于是,我根据自己的需要,为NetScaler 8.0写了一个MySQL Slave数据库负载均衡健康检查脚本(nsmysql-slave.pl),实现了上述需求。

  有了“nsmysql-slave.pl”做健康检查,利用NetScalerVIP(虚拟IP),就可以完美实现多台MySQL Slave数据库的负载均衡了。当一台MySQL Slave数据库出现不同步、表损坏、同步延迟过大(本脚本中默认设置的落后MySQL主库600秒视为延迟,可根据具体应用修改)、活动连程数太高(本脚本中默认设置的是大于200视为连程数太高,可根据具体应用修改)等情况,“nsmysql-slave.pl”就会自动将其检查出来,并告知NetScalerNetScaler会将该数据库标识为宕机,从而不将用户的查询请求传送到这台发生故障的数据库上。故障一旦修复,“nsmysql-slave.pl”会自动告知NetScaler,该数据库已经可以使用。

“nsmysql-slave.pl”源代码如下:  

view plaincopy to clipboardprint?

1.       #!/usr/bin/perl -w   

2.       ################################################################   

3.       ##   

4.       ## MySQL Slave Server Monitoring Script V1.1 for NetScaler 8.x   

5.       ## Written by Zhang Yan (blog.s135.com) on   

6.       ##   

7.       ################################################################   

8.       ## This is a netscaler supplied script.    

9.         

10.   ## This script is used to do MySQL slave server monitoring   

11.   ## using KAS feature.   

12.   ## The mandatory arguments are:   

13.   ##      1. Database to which the user is going to connect   

14.   ##      2. User name   

15.   ## The optional arguments are:   

16.   ##      1. password:  This is the password that will be used to   

17.   ##                    login into the server. If no password is   

18.   ##                    given a blank password is used.   

19.   ##      2. SQL query   

20.   ## Example:   

21.   ##              set monitor ...  -scriptArgs "database=test;user=user1;password=password;   

22.   ##                                                                              query=show slave status"   

23.     

24.     

25.   use strict;   

26.   use DBI;   

27.   use Netscaler::KAS;   

28.     

29.   ## This function is a handler for performing MYSQL probe in KAS mode   

30.   sub mysql_probe   

31.   {   

32.           ## There must be at least 3 arguments to this function.   

33.           ##      1. First argument is the IP that has to be probed.   

34.           ##      2. Second argument is the port to connect to.   

35.           ##      3. Arguments to be used during probing.   

36.           if(scalar(@_) < 3)   

37.           {   

38.                   return (1,"Arguments not given");   

39.           }   

40.     

41.           ## Parse the argument given, to get database,user name,password,SQL query.   

42.           ## If parsing fails, it is monitoring probe failure.   

43.           $_[2]=~/database=([^;]+);user=([^;]+)(;password=([^;]+))?(;query=([^;]+))?/    

44.                   or return (1,"Invalid argument format");   

45.     

46.           (my $database,my $username,my $password,my $sql_query)=($1,$2,$4,$6);   

47.     

48.           ## If no password is given, try blank password   

49.           if(!defined($password))   

50.           {   

51.                   $password="";   

52.           }   

53.     

54.           ## Try to connect to the server   

55.           my $db_handle = DBI->connect("dbi:mysql:database=$database:host=$_[0]:$_[1]",$username,$password)   

56.                   or return (1,"Connection to database failed - $!");   

57.     

58.           ## Check MySQL Slave Server   

59.           my $slave_info = $db_handle->prepare("show slave status");   

60.           $slave_info->execute()   

61.                   or return (1,"Execution of SQL query failed");   

62.           my $slave_ref = $slave_info->fetchrow_hashref()   

63.                   or return (1,"Fetchrow of SQL query failed");   

64.     

65.           my $threads_info = $db_handle->prepare("show global status like 'Threads_running'");   

66.           $threads_info->execute()   

67.                   or return (1,"Execution of SQL query failed");   

68.           my $threads_ref = $threads_info->fetchrow_hashref()   

69.                   or return (1,"Fetchrow of SQL query failed");   

70.     

71.           if (exists $slave_ref->{Slave_SQL_Running} and $slave_ref->{Slave_SQL_Running} eq 'No')   

72.           {   

73.         $db_handle->disconnect();   

74.               return (1,"Slave IO thread has stopped");   

75.           }   

76.           elsif (exists $slave_ref->{Slave_IO_Running} and $slave_ref->{Slave_IO_Running} eq 'No')   

77.           {   

78.         $db_handle->disconnect();   

79.               return (1,"Slave IO thread has stopped");   

80.           }   

81.           elsif (exists $slave_ref->{Last_Error} and $slave_ref->{Last_Error} ne '')   

82.           {   

83.         $db_handle->disconnect();   

84.               return (1,"Has some error information");   

85.           }   

86.           elsif (exists $slave_ref->{Seconds_Behind_Master} and $slave_ref->{Seconds_Behind_Master} > 600)   

87.           {   

88.         $db_handle->disconnect();   

89.               return (1,"The seconds behind master more than 600");   

90.           }       

91.           elsif (exists $threads_ref->{Value} and $threads_ref->{Value} > 200)   

92.           {   

93.         $db_handle->disconnect();   

94.               return (1,"The number of threads that are not sleeping more than 200");   

95.           }   

96.           else  

97.           {   

98.               ## If no query is given then it is probe success , else try executing the query   

99.               if(!defined($sql_query))   

100.                {   

101.                        $db_handle->disconnect();   

102.                        return 0;   

103.                }   

104.      

105.                ## Problem during query execution, report failure   

106.                my $statement = $db_handle->prepare($sql_query)   

107.                        or return (1,"Preparation of SQL query failed");   

108.      

109.                $statement->execute()   

110.                        or return (1,"Execution of SQL query failed");   

111.            }   

112.      

113.            ## Probe Succeeded.   

114.            $db_handle->disconnect();   

115.      

116.            return 0;   

117.    }   

118.      

119.    ## Register MS SQL probe handler, to the KAS module.   

120.    probe(&mysql_probe);  

  脚本压缩包下载:

下载文件 (已下载 83 )

点击这里下载文件



  健康检查脚本写完了,现在开始配置NetScaler 8.0

1、使用SecureCRTSSH客户端工具登录到NetScaler,然后执行以下命令:

shell
cd /nsconfig/monitors/
vi nsmysql-slave.pl


  将“nsmysql-slave.pl”的源代码粘贴到其中,然后保存退出,再执行以下命令:

chmod +x nsmysql-slave.pl



2、检查一下从NetScaler上是否能够连接MySQL Slave数据库:

mysql -u 用户名 -p -h 192.168.1.31 -P 3306


Enter password:(在此输入MySQL登录密码)

ERROR 1251: Client does not support authentication protocol requested by server; consider upgrading MySQL client

  如果你的MySQL Slave服务器版本高于4.0,就会出现以上错误。这是因为MySQL 4.1及其以上版本的密码验证算法与MySQL 4.0及其以下版本不同,而NetScaler 8.0上的MySQL客户端默认版本为4.0.25,因此,4.0.25版本的MySQL客户端连接4.15.X6.X版本的MySQL服务器就会出错。

  解决办法1:升级NetScaler 8.0上的MySQL客户端,但最好不要这么做,因为NetScaler与底层的FreeBSD系统和应用软件嵌入很密切的,不要轻易替换成非官方版本,以免导致不兼容、不稳定等情况。

  解决方法2:在各台MySQL Slave服务器上新建一个名为“netscaler”的超级管理员帐号,将密码改为使用旧加密算法进行加密的密码。如果从安全考虑,可将以下语句中的%换成NetScalerSubnet IP
Server version: 5.1.24-rc MySQL Community Server (GPL)
Type 'help;' or 'h' for help. Type 'c' to clear the buffer.
mysql>

GRANT ALL PRIVILEGES ON *.* TO 'netscaler'@'%' IDENTIFIED BY OLD_PASSWORD('12345678');
FLUSH PRIVILEGES;



3、各台MySQL Slave数据库必须添加允许NetScalerSubnet IP访问的帐号,因为在同一网段,不能开启源IP支持,MySQL服务器上看到的将是NetScalerSubnet IP

  例如:【Web服务器(192.168.1.21)】──→NetScaler VIP192.168.1.5)】- - - NetScaler Subnet IP192.168.1.2)】──→MySQL Slave服务器(192.168.1.31)】
MySQL Slave服务器看到的是IP地址是192.168.1.2,就需要添加NetScalerSubnet IP访问的帐号('apache'@'192.168.1.2'):
Server version: 5.1.24-rc MySQL Community Server (GPL)
Type 'help;' or 'h' for help. Type 'c' to clear the buffer.
mysql>

GRANT ALL PRIVILEGES ON *.* TO 'apache'@'192.168.1.2' IDENTIFIED BY '12345678';
FLUSH PRIVILEGES;



4、从Web管理界面登录NetScaler 8.0,进入Configuration页面(需要安装Java Runtime Environment,版本在JRE 1.4.x+以上):



5、点击【Load Balancing──Monitors】栏的“add”按钮,添加一个名为“mysql_slave”MySQL健康检查:

Interval:正常情况下,10秒钟检查一次;
Response Timeout:每次检查的超时时间为8秒,必须小于Interval
Down Time:宕机状态下,每5秒钟检查一次;
Retries:重试5次后仍然检查失败,标记服务器为宕机;
Type:选择MySQL
Script Name:点击其后的“Browse...”按钮,选择我编写的MySQL Slave健康检查脚本“nsmysql-slave.pl”
Dispatcher IPDispatcher Port必须填“127.0.0.1”“3013”,不要改变;
User Name输入刚才创建的帐号“netscaler“password输入创建帐号时设定的“12345678”



6、点击【Load Balancing──Service Groups】栏的“add”按钮,添加一个名为“pool_mysql”MySQL服务器池:

、添加真实MySQL Slave服务器到“pool_mysql”服务器池,协议选择TCP

、健康检查方式选择第5步中创建的“mysql_slave”



7、点击【Load Balancing──Virtual Servers】栏的“add”按钮,添加一个名为“vs_mysql_slave”VIP(虚拟IP):

、添加“pool_mysql”服务器池到名为“vs_mysql_slave”VIP192.168.1.5:3306),协议选择TCP

、负载均衡方式选择Least Connection(最小连接数):



8Web服务器要访问MySQL Slave,只需访问NetScalerVIP──192.168.1.53306端口即可。至此,已经完美解决多台MySQL Slave数据库的负载均衡问题。

[文章作者:张宴本文版本:v1.1 最后修改:2008.07.17 转载请注明出自:http://blog.s135.com]

给我留言

Copyright © 浩然东方 保留所有权利.   Theme  Ality 07032740

用户登录