HAProxy is an open source software which can load balance HTTP and TCP servers. All your MySQL servers have to be configured to perform Master-Master replication as load balancing involves both reading and writing to all the backends.
Prepare MySQL Servers
HAproxy over MySQL |
We need to prepare the MySQL servers by creating one additional user for HAProxy. This user will be used by HAProxy to check the status of a server and health of server.
mysqlchk
We need to create a script which detects the MySQL replication role on the database node as per below:
- if master (SHOW SLAVE HOSTS > 1 AND read_only = OFF),
- return 'MySQL master is running.'
- if slave (Slave_IO_Running = Yes AND Slave_SQL_Running = Yes AND (Seconds_Behind_Master = 0 OR Seconds_Behind_Master < SLAVE_LAG_LIMIT))
- Set limit of SLAVE_LAG_LIMIT which will be bear able for your environment.
- return 'MySQL slave is running. (slave lag: 0)'
- else
- return 'MySQL is *down*'
How to use
- Create a script in any path like I created at '/opt/mysqlcheck' and make it executable.
#!/bin/bashSLAVE_LAG_LIMIT=5MYSQL_HOST="127.0.0.1"MYSQL_PORT="3306"MYSQL_USERNAME='USERNAME'MYSQL_PASSWORD='PASSWORD'MYSQL_BIN='/usr/bin/mysql'MYSQL_OPTS="-q -A --connect-timeout=10"TMP_FILE="/tmp/mysqlchk.$$.out"ERR_FILE="/tmp/mysqlchk.$$.err"FORCE_FAIL="/tmp/proxyoff"preflight_check(){for I in "$TMP_FILE" "$ERR_FILE"; doif [ -f "$I" ]; thenif [ ! -w $I ]; thenecho -e "HTTP/1.1 503 Service Unavailable\r\n"echo -e "Content-Type: Content-Type: text/plain\r\n"echo -e "\r\n"echo -e "Cannot write to $I\r\n"echo -e "\r\n"exit 1fifidone}return_ok(){echo -e "HTTP/1.1 200 OK\r\n"echo -e "Content-Type: text/html\r\n"echo -e "Content-Length: 43\r\n"echo -e "\r\n"if [ $role == "master" ]; thenecho -e "<html><body>MySQL master is running.</body></html>\r\n"elif [ $role == "slave" ]; thenecho -e "<html><body>MySQL slave is running. (Slave lag: $SLAVE_LAG)</body></html>\r\n"elseecho -e "<html><body>MySQL is running.</body></html>\r\n"fiecho -e "\r\n"# rm $ERR_FILE $TMP_FILEexit 0}return_fail(){echo -e "HTTP/1.1 503 Service Unavailable\r\n"echo -e "Content-Type: text/html\r\n"echo -e "Content-Length: 42\r\n"echo -e "\r\n"echo -e "<html><body>MySQL is *down*.</body></html>\r\n"echo -e "\r\n"exit 1}preflight_checkif [ -f "$FORCE_FAIL" ]; thenecho "$FORCE_FAIL found" > $ERR_FILEreturn_failfiCMDLINE="$MYSQL_BIN $MYSQL_OPTS --host=$MYSQL_HOST --port=$MYSQL_PORT --user=$MYSQL_USERNAME --password=$MYSQL_PASSWORD -e"SLAVE_IO=$(${CMDLINE} 'SHOW REPLICA STATUS' --vertical 2>/dev/null | grep Replica_IO_Running | tail -1 | awk {'print $2'})SLAVE_SQL=$(${CMDLINE} 'SHOW REPLICA STATUS' --vertical 2>/dev/null | grep Replica_SQL_Running | head -1 | awk {'print $2'})echo $CMDLINEif [[ "${SLAVE_IO}" == "Yes" ]] && [[ "${SLAVE_SQL}" == "Yes" ]]; thenrole='slave'SLAVE_LAG=$(${CMDLINE} 'SHOW REPLICA STATUS' --vertical 2>/dev/null | grep Seconds_Behind_Source | tail -1 | awk {'print $2'})if [[ $SLAVE_LAG = 0 ]]; thenreturn_okelif [ $SLAVE_LAG -lt $SLAVE_LAG_LIMIT ] ; thenreturn_okfielserole='master'READ_ONLY=$($CMDLINE 'SHOW GLOBAL VARIABLES LIKE "read_only"' --vertical 2>/dev/null | tail -1 | awk {'print $2'})echo "$READ_ONLY"[[ "${READ_ONLY}" == "OFF" ]] && return_okfireturn_fail
- Create a service in /etc/xinetd.d/ and accordingly change /etc/service with port number and service name.
service mysqlchk{flags = REUSEsocket_type = streamport = 9300wait = noserver = /root/mysqlchkuser = mysqllog_on_failure += USERIDdisable = noonly_from = 0.0.0.0/0 # recommended to put the IPs that need# to connect exclusively (security purposes)per_source = UNLIMITED # Recently added (May 20, 2010)}
- restart xinetd service
- Install HAProxy on the your selected node.
- Update require information (SLAVE_LAG_LIMIT is in seconds):
- SLAVE_LAG_LIMIT=5
- MYSQL_HOST="localhost"
- MYSQL_PORT="3306"
- MYSQL_USERNAME='root'
- MYSQL_PASSWORD='password'
- You are good to go. Now ensure in HAProxy you have 2 listeners (3307 for write, 3308 for read) and use option tcp-check & tcp-check expect to distinguish master/slave similar to example below:
- listen haproxy_aa,aa,aa,aa_3307_write
- bind *:3307
- mode tcp
- timeout client 10800s
- timeout server 10800s
- balance leastconn
- option tcp-check
- tcp-check expect string MySQL\ master
- option allbackups
- default-server port 9200 inter 2s downinter 5s rise 3 fall 2 slowstart 60s maxconn 64 maxqueue 128 weight 100
- server xx.xx.xx.xx xx.xx.xx.xx:3306 check
- server yy.yy.yy.yy yy.yy.yy.yy:3306 check
- server zz.zz.zz.zz zz.zz.zz.zz:3306 check
- listen haproxy_aa,aa,aa,aa_3308_read
- bind *:3308
- mode tcp
- timeout client 10800s
- timeout server 10800s
- balance leastconn
- option tcp-check
- tcp-check expect string is\ running.
- option allbackups
- default-server port 9200 inter 2s downinter 5s rise 3 fall 2 slowstart 60s maxconn 64 maxqueue 128 weight 100
- server xx.xx.xx.xx xx.xx.xx.xx:3306 check
- server yy.yy.yy.yy yy.yy.yy.yy:3306 check
- server zz.zz.zz.zz zz.zz.zz.zz:3306 check
No comments:
Post a Comment