背景
在上一篇文章美團點評DBProxy讀寫分離使用說明實現了讀寫分離,但在最后提了二個問題:一是代理不管MySQL主從的復制狀態,二是DBProxy本身是一個單點的存在。對於第一個可以通過自己定義的檢測規則進行操作Admin接口,實現主從狀態異常的處理。而對於第二個問題,需要再起一個DBProxy來防止單點故障,本文通過介紹LVS來實現DBProxy的負載均衡和高可用。MySQL的架構如下:
LVS基礎
http://www.linuxvirtualserver.org/zh/lvs1.html
http://www.linuxvirtualserver.org/zh/lvs2.html
http://www.linuxvirtualserver.org/zh/lvs3.html
http://www.linuxvirtualserver.org/zh/lvs4.html
1)LVS是什么
LVS是Linux Virtual Server的簡稱,也就是Linux虛擬服務器。主要用於服務器集群的負載均衡。它是四層負載均衡,建立在OSI模型的第四層——傳輸層之上,傳輸層上有我們熟悉的 TCP/UDP。轉發主要通過修改IP地址(NAT 模式)、修改目標 MAC(DR 模式)來實現。它工作在網絡層,可以實現高性能,高可用的服務器集群技術,可把許多低性能的服務器組合在一起形成一個超級服務器。配置非常簡單,且有多種負載均衡的方法。即使在集群的服務器中某台服務器無法正常工作,也不影響整體效果。另外可擴展性也非常好。LVS的體系結構如下:
(1)最前端的負載均衡層,用Load Balancer表示,用於負載均衡調度。(LVS)
(2)中間的服務器集群層,用Server Array表示,用於存放真實服務器。(DBProxy)
(3)最底端的數據共享存儲層,用Shared Storage表示;(MySQL)
在用戶看來,所有的內部應用都是透明的,用戶只是在使用一個虛擬服務器提供的高性能服務。
2)LVS模式
這里詳細介紹DR和NAT模式
- DR:直接路由模式,DR 模式下需要 LVS 和RS綁定同一個 VIP(RS 通過將 VIP 綁定在 loopback 實現)。
LVS接收請求,由真實提供服務的服務器(RealServer, RS)直接返回給用戶,返回的時候不經過LVS。即一個請求過來時,LVS只需要將網絡幀的MAC地址修改為某一台RS的MAC,該包就會被轉發到相應的RS處理,注意此時的源IP和目標IP都沒變。RS收到LVS轉發來的包時,鏈路層發現MAC是自己的,到上面的網絡層,發現IP也是自己的,於是這個包被合法地接收,RS感知不到前面有LVS的存在。而當RS返回響應時,只要直接向源IP(即用戶的IP)返回即可,不再經過LVS。
特性:
①:調度服務器(director server)只接收client請求和轉發到realserver,realserver再回應client,不需要在經過調度服務器,效率高。
②:不支持端口映射和跨域LAN。
- NAT:網絡地址轉換,網絡數據包的進出都要經過LVS的處理,LVS物理IP做為RS的網關。
NAT(Network Address Translation)是一種外網和內網地址映射的技術。NAT模式下,網絡數據包的進出都要經過LVS的處理。LVS需要作為RS(真實服務器)的網關。當包到達LVS時,LVS做目標地址轉換(DNAT),將目標IP改為RS的IP。RS接收到包以后,仿佛是客戶端直接發給它的一樣。RS處理完,返回響應時,源IP是RS IP,目標IP是客戶端的IP。這時RS的包通過網關(LVS)中轉,LVS會做源地址轉換(SNAT),將包的源地址改為VIP,這樣,這個包對客戶端看起來就仿佛是LVS直接返回給它的。客戶端無法感知到后端RS的存在。
特性:
①:調度服務器(director server)接收client請求和轉發到realserver,realserver再回應調度服務器,調度服務器再回應client, 調度服務器會成為瓶頸,效率低。
②:realserver和director server處於同一網絡,僅於director server通訊,並且網絡需要指向director server。
③:director server支持端口映射,可以將客戶端請求的端口映射到realserver的另一個端口,DR模式不行。原因是NAT響應需要經過director server,DR則直接和客戶端響應。
- TUNNEL:IP隧道模式,主要用於RS不同一個地點的網絡,支持跨域LAN。
- FULL-NAT
3)調度算法
LVS的調度算法決定了如何在集群節點之間分布工作負荷。當director調度器收到來自客戶端訪問VIP的上的集群服務的入站請求時,director調度器必須決定哪個集群節點應該處理請求。Director調度器用的調度方法基本分為兩類:
固定調度算法:rr,wrr,dh,sh
動態調度算法:wlc,lc,lblc,lblcr,sed,nq
算法 |
說明 |
rr |
輪詢算法,它將請求依次分配給不同的rs節點,也就是RS節點中均攤分配。這種算法簡單,但只適合於RS節點處理性能差不多的情況 |
wrr |
加權輪訓調度,它將依據不同RS的權值分配任務。權值較高的RS將優先獲得任務,並且分配到的連接數將比權值低的RS更多。相同權值的RS得到相同數目的連接數。 |
wlc |
加權最小連接數調度,假設各台RS的全職依次為Wi,當前tcp連接數依次為Ti,依次去Ti/Wi為最小的RS作為下一個分配的RS |
dh |
目的地址哈希調度(destination hashing)以目的地址為關鍵字查找一個靜態hash表來獲得需要的RS |
sh |
源地址哈希調度(source hashing)以源地址為關鍵字查找一個靜態hash表來獲得需要的RS |
lc |
最小連接數調度(least-connection),IPVS表存儲了所有活動的連接。LB會比較將連接請求發送到當前連接最少的RS. |
lblc |
基於地址的最小連接數調度(locality-based least-connection):將來自同一個目的地址的請求分配給同一台RS,此時這台服務器是尚未滿負荷的。否則就將這個請求分配給連接數最小的RS,並以它作為下一次分配的首先考慮。 |
LVS更多的相關知識可以見官網說明,下面開始部署測試。
LVS+DBProxy
環境:
LVS的模式是DR,調度算法是wlc。 系統:Ubuntu 16.04 director server :192.168.200.2 real server : 192.168.200.10/12 已經裝上了DBProxy,3309是管理接口,3308是數據訪問接口 VIP : 192.168.200.1
內核已集成ipvs模塊,只需在DS服務器上安裝管理工具:
apt-get install ipvsadm
知識點說明:
在LVS的DR模式下,從上面圖中也可以看到,調度服務器(DS)和真實服務器(RS)都綁定了VIP,請求過來如何讓DS來響應請求?RS不響應?這時需要獲取mac地址在第2層進行通訊(和DS來綁定),只和DS來響應。通過系統參數arp_ignore(1)限制RS不去接收請求。接着DS收到請求之后需要把請求發給RS服務器,這時RS服務器需要通過系統參數arp_announce(2)來隱藏其接收的接口(物理IP所在網卡)不回應,讓其回環地址lo去響應客戶端(需要設置一個路由)。
設置:
1)director server設置(臨時)
在任意一個網卡(eth1:0)上添加vip:廣播地址設置成vip,子網掩碼4個255,用於對外提供服務 ifconfig eth1:0 192.168.200.1 broadcast 192.168.200.1 netmask 255.255.255.255 up 添加路由:從指定的網卡路由 route add -host 192.168.200.1 dev eth1:0 啟用系統的包轉發功能echo
"1"
>/proc/sys/net/ipv4/ip_forward
查看路由信息 root@LVS-Director:~# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default sfgw.host.dxy 0.0.0.0 UG 0 0 0 eth1 192.168.200.0 * 255.255.255.0 U 0 0 0 eth1 192.168.200.1 * 255.255.255.255 UH 0 0 0 eth1
查看LVS信息:ipvsadm -ln
root@LVS-Director:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn
InActConn 指非活躍連接數,我們將處於 TCP ESTABLISH 狀態以外的連接都稱為不活躍連接。例如處於 SYN_RECV 狀態的連接,處於 TIME_WAIT 狀態的連接等。 ActiveConn指活動連接數 Weight:權重
添加虛擬服務: ipvsadm -A(添加虛擬服務器) -t(處理tcp) $vip:port(虛擬IP:端口) -s wlc(調度算法)
添加一個通過虛擬IP 3308端口的tcp服務,wlc的調度算法
root@LVS-Director:~# ipvsadm -A -t 192.168.200.1:3308 -s wlc root@LVS-Director:~# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.200.1:3308 wlc
添加真實服務器:ipvsadm -a(添加真實服務器) -t(處理tcp) $vip:port(真實IP:端口) -g(LVS模式) -r(真實服務器) $realserver(真實服務器IP) -w 1(權重)
添加真實服務器,-g:DR直接路由模式,-w權重
root@LVS-Director:~# ipvsadm -a -t 192.168.200.1:3308 -g -r 192.168.200.10 -w 1 #真實服務器1 root@LVS-Director:~# ipvsadm -a -t 192.168.200.1:3308 -g -r 192.168.200.12 -w 2 #真實服務器2 root@LVS-Director:~# ipvsadm -L -n IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.200.1:3308 wlc -> 192.168.200.10:3308 Route 1 0 0 -> 192.168.200.12:3308 Route 2 0 0
保存LVS:save
root@LVS-Director:~# /etc/init.d/ipvsadm save * Saving IPVS configuration... [ OK ]
2)real server設置(臨時)
修改系統參數: echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce 回環地址lo設置vip,廣播地址設置成vip,子網掩碼設置成4個255,和DR的VIP保持通訊。 ifconfig lo:0 192.168.200.1 broadcast 192.168.200.1 netmask 255.255.255.255 up 添加路由,從指定的網卡路由 route add -host 192.168.200.1 dev lo:0 root@LVS-RS1:~# route Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface default 192.168.200.254 0.0.0.0 UG 0 0 0 eth0 192.168.200.0 * 255.255.255.0 U 0 0 0 eth0 192.168.200.1 * 255.255.255.255 UH 0 0 0 lo
3)LVS設置,使用ipvsadm來設置管理。
ipvsadm v1.28 2015/02/09 (compiled with popt and IPVS v1.2.1) Usage:用法
#添加/修改一個虛擬服務,包括協議(tcp、udp...),調度算法,超時等。 ipvsadm -A|E virtual-service [-s scheduler] [-p [timeout]] [-M netmask] [--pe persistence_engine] [-b sched-flags]
#刪除一條虛擬服務 ipvsadm -D virtual-service
#清除整個虛擬服務器表中的所有記錄 ipvsadm -C
#恢復虛擬服務器規則 ipvsadm -R
#保存虛擬服務器規則 ipvsadm -S [-n]
#添加/修改真實服務器,包括LVS模式、權重、超時等 ipvsadm -a|e virtual-service -r server-address [options]
#刪除真實服務器 ipvsadm -d virtual-service -r server-address
#顯示虛擬服務器列表 ipvsadm -L|l [virtual-service] [options]
#虛擬服務表計數器清零 ipvsadm -Z [virtual-service]
#設置連接超時值 ipvsadm --set tcp tcpfin udp
#啟動同步守護進程。在這個功能上也可以采keepalived 的VRRP 功能。 ipvsadm --start-daemon state [--mcast-interface interface] [--syncid sid]
#關閉守護進程 ipvsadm --stop-daemon state ipvsadm -h Commands: Either long or short options are allowed. --add-service -A add virtual service with options #添加虛擬服務器 --edit-service -E edit virtual service with options #修改虛擬服務器 --delete-service -D delete virtual service #刪除虛擬服務器 --clear -C clear the whole table #清除虛擬服務器規則 --restore -R restore rules from stdin #還原虛擬服務器規則 --save -S save rules to stdout #保存虛擬服務器規則 --add-server -a add real server with options #添加真實服務器 --edit-server -e edit real server with options #修改真實服務器 --delete-server -d delete real server #刪除真是服務器 --list -L|-l list the table #顯示虛擬服務器列表 --zero -Z zero counters in a service or all services #虛擬服務表計數器清零(清空當前的連接數量等) --set tcp tcpfin udp set connection timeout values #連接超時 --start-daemon start connection sync daemon #開啟守護進程 --stop-daemon stop connection sync daemon #關閉守護進程 --help -h display this help message virtual-service: --tcp-service|-t service-address service-address is host[:port] #虛擬服務器提供的是tcp 的服務 --udp-service|-u service-address service-address is host[:port] #虛擬服務器提供的是udp 的服務 --sctp-service service-address service-address is host[:port] #虛擬服務器提供的時sctp(流控制傳輸協議)的服務 --fwmark-service|-f fwmark fwmark is an integer greater than zero #經過iptables 標記過的服務類型 Options: --ipv6 -6 fwmark entry uses IPv6 #使用ipv6 --scheduler -s scheduler one of rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|nq, #調度算法,默認是使用wlc the default scheduler is wlc. --pe engine alternate persistence engine may be sip, not set by default. --persistent -p [timeout] persistent service #持久穩固的服務。這個選項的意思是來自同一個客戶的多次請求,將被同一台真實的服務器處理。timeout 的默認值為300 秒 --netmask -M netmask persistent granularity mask --real-server -r server-address server-address is host (and port) #真實服務器地址和端口 --gatewaying -g gatewaying (direct routing) (default) #LVS直接路由模式(DR),默認。 --ipip -i ipip encapsulation (tunneling) #LVS 隧道模式 --masquerading -m masquerading (NAT) #LVS NAT模式 --weight -w weight capacity of real server #真實服務器權重 --u-threshold -x uthreshold upper threshold of connections #最大連接 --l-threshold -y lthreshold lower threshold of connections #最小連接 --mcast-interface interface multicast interface for connection sync --syncid sid syncid for connection sync (default=255) --connection -c output of current IPVS connections #顯示LVS 目前的連接,如:ipvsadm -L -c --timeout output of timeout (tcp tcpfin udp) #顯示tcp tcpfin udp 的timeout 值 如:ipvsadm -L --timeout --daemon output of daemon information #顯示同步守護進程狀態 --stats output of statistics information #顯示統計信息,統計自該條轉發規則生效以來的包 --rate output of rate information #顯示速率信息 --exact expand numbers (display exact values) --thresholds output of thresholds information --persistent-conn output of persistent connection info --nosort disable sorting output of service/server entries --sort does nothing, for backwards compatibility #對虛擬服務器和真實服務器排序輸出 --ops -o one-packet scheduling --numeric -n numeric output of addresses and ports #輸出IP 地址和端口的數字形式 --sched-flags -b flags scheduler flags (comma-separated)
監控相關狀態:
--stats:是統計自該條轉發規則生效以來的信息
root@LVS-Director:~# ipvsadm -l --stats IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes -> RemoteAddress:Port TCP 192.168.200.1:3308 4 42 0 2711 0 -> 192.168.200.10:3308 1 11 0 680 0 -> 192.168.200.12:3308 3 31 0 2031 0 Conns (connections scheduled) 已經轉發過的連接數 InPkts (incoming packets) 入包個數 OutPkts (outgoing packets) 出包個數 InBytes (incoming bytes) 入流量(字節) OutBytes (outgoing bytes) 出流量(字節)
--rate:顯示速率信息
root@LVS-Director:~# ipvsadm -l --rate IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port CPS InPPS OutPPS InBPS OutBPS -> RemoteAddress:Port TCP 192.168.200.1:3308 0 0 0 0 0 -> 192.168.200.10:3308 0 0 0 0 0 -> 192.168.200.12:3308 0 0 0 0 0 CPS (current connection rate) 每秒連接數 InPPS (current in packet rate) 每秒的入包個數 OutPPS (current out packet rate) 每秒的出包個數 InBPS (current in byte rate) 每秒入流量(字節) OutBPS (current out byte rate) 每秒入流量(字節)
現在通過訪問192.168.200.1的3308端口,直接就可以按照調度算法進行訪問下面真實服務器的端口服務了。
4)測試
訪問 [zhoujy@localhost ~]$ mysql -usbtest -psbtest -P3308 -h192.168.200.1 ... sbtest@192.168.200.1 : (none) 02:35:54>show databases; +--------------------+ | Database | +--------------------+ | information_schema | | sbtest | +--------------------+ 關閉200.10的DBProxy,看看能否繼續訪問 root@LVS-RS1:/usr/local/mysql-proxy# ./bin/mysql-proxyd test_proxy stop OK: MySQL-Proxy of test_proxy is stopped 訪問: root@LVS-RS2:~# mysql -usbtest -psbtest -P3308 -h127.0.0.1 ... mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | sbtest | +--------------------+ 2 rows in set (0.00 sec)
從上面看到關閉了一台DBProxy,可以繼續訪問。這樣DBProxy的單點故障的問題解決了
啟動腳本
開啟LVS的相關命令步驟上面已經大致講完,上面的設置都是臨時的,重啟之后都會無效,這里可以編寫一個啟動腳本:
1)Director Server:directorserver
#!/bin/bash VIP=192.168.200.1 RIP1=192.168.200.10 RIP2=192.168.200.12 case "$1" in start) echo "開始啟動LVS Director Server..." ifconfig eth1:0 $VIP broadcast $VIP netmask 255.255.255.255 up route add -host $VIP dev eth1:0 echo "1">/proc/sys/net/ipv4/ip_forward sysctl -p >/dev/null 2>&1 ipvsadm -C ipvsadm -A -t $VIP:3308 -s rr ipvsadm -a -t $VIP:3308 -r $RIP1 -g -w 1 ipvsadm -a -t $VIP:3308 -r $RIP2 -g -w 2 ipvsadm --save echo "開啟成功!" ;; stop) echo "正在關閉LVS Director Server..." echo "0">/proc/sys/net/ipv4/ip_forward ipvsadm -C ifconfig eth1:0 down echo "關閉成功!" ;; *) echo "用法:$0 {start|stop}" exit 1 esac
使用:
/etc/init.d/directorserver start
/etc/init.d/directorserver stop
2)Real Server:realserver
#!/bin/bash VIP=192.168.200.1 case "$1" in start) echo "啟動LVS Real Server..." ifconfig lo:0 $VIP broadcast $VIP netmask 255.255.255.255 up route add -host $VIP dev lo:0 echo 1 > /proc/sys/net/ipv4/conf/lo/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/lo/arp_announce echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce sysctl -p >/dev/null 2>&1 echo "開啟成功!" ;; stop) echo "正在關閉LVS Real server" ifconfig lo:0 down echo "0" >/proc/sys/net/ipv4/conf/lo/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/all/arp_ignore echo "0" >/proc/sys/net/ipv4/conf/lo/arp_announce echo "0" >/proc/sys/net/ipv4/conf/all/arp_announce echo "關閉成功!" ;; *) echo "用法:$0 {start|stop}" exit 1 esac
使用:
/etc/init.d/realserver start
/etc/init.d/realserver stop
上面通過LVS實現了RS的高可用,然而LVS本身也是有單點的,這個可以通過Keepalived來實現LVS的高可用,下面來說明下Keepalived的相關說明。
LVS+Keepalived+DBProxy
1)安裝keepalived
關於Keepalived的說明可以看官網和keepalived工作原理和配置說明
Keepalived是一個基於VRRP協議來實現的WEB 服務高可用方案,可以利用其來避免單點故障。一個服務至少會有2台服務器運行Keepalived,一台為主服務器(MASTER),一台為備份服務器(BACKUP),但是對外表現為一個虛擬IP,主服務器會發送特定的消息給備份服務器,當備份服務器收不到這個消息的時候,即主服務器宕機的時候,備份服務器就會接管虛擬IP,繼續提供服務,從而保證了高可用性。其的工作原理:
keepalived是以VRRP協議為實現基礎的,VRRP全稱Virtual Router Redundancy Protocol,即虛擬路由冗余協議。虛擬路由冗余協議,可以認為是實現路由器高可用的協議,即將N台提供相同功能的路由器組成一個路由器組,這個組里面有一個master和多個backup,master上面有一個對外提供服務的vip(該路由器所在局域網內其他機器的默認路由為該vip),master會發組播,當backup收不到vrrp包時就認為master宕掉了,這時就需要根據VRRP的優先級來選舉一個backup當master。這樣的話就可以保證路由器的高可用了。keepalived主要有三個模塊,分別是core、check和vrrp。core模塊為keepalived的核心,負責主進程的啟動、維護以及全局配置文件的加載和解析。check負責健康檢查,包括常見的各種檢查方式。vrrp模塊是來實現VRRP協議的。
下載Keepalived
wget http://www.keepalived.org/software/keepalived-1.3.5.tar.gz
編譯安裝Keepalived(根據提示安裝相關的依賴包):
./configure make make install
安裝成功
root@LVS-Director:~# keepalived -h Usage: keepalived [OPTION...] -f, --use-file=FILE Use the specified configuration file -P, --vrrp Only run with VRRP subsystem -C, --check Only run with Health-checker subsystem -l, --log-console Log messages to local console -D, --log-detail Detailed log messages -S, --log-facility=[0-7] Set syslog facility to LOG_LOCAL[0-7] -X, --release-vips Drop VIP on transition from signal. -V, --dont-release-vrrp Don't remove VRRP VIPs and VROUTEs on daemon stop -I, --dont-release-ipvs Don't remove IPVS topology on daemon stop -R, --dont-respawn Don't respawn child processes -n, --dont-fork Don't fork the daemon process -d, --dump-conf Dump the configuration data -p, --pid=FILE Use specified pidfile for parent process -r, --vrrp_pid=FILE Use specified pidfile for VRRP child process -c, --checkers_pid=FILE Use specified pidfile for checkers child process -a, --address-monitoring Report all address additions/deletions notified via netlink -s, --namespace=NAME Run in network namespace NAME (overrides config) -m, --core-dump Produce core dump if terminate abnormally -M, --core-dump-pattern=PATN Also set /proc/sys/kernel/core_pattern to PATN (default 'core') -i, --config_id id Skip any configuration lines beginning '@' that don't match id -v, --version Display the version number -h, --help Display this help message
編譯可以參考http://www.cnblogs.com/tugeler/p/6621959.html和http://xg2007524.blog.51cto.com/869106/1363643。也可以直接apt-get install 安裝。
2)Keepalived配置
在上面介紹了自己編寫啟動腳本啟動LVS,通過Keepalived可以代替directorserver的啟動腳本。要實現LVS的高可用,需要再起一台LVS服務器,通過Keepalived在2台LVS服務器上配置一個主和備來相互檢測。如:啟動一台IP為192.168.200.24(eth0)服務器,安裝上ipvsadm和Keepalived。
① MASTER Keepalived配置(192.168.200.2,/etc/keepalived/keepalived.conf):
! Configuration File for keepalived #global_defs區域:主要是配置故障發生時的通知對象以及機器標識 global_defs { notification_email { zjy@xxx.com } notification_email_from keepalived@smtp.dxy.cn smtp_server 192.168.200.254 smtp_connect_timeout 30 #設置lvs的id router_id LVS_Masterdata_M } #用來定義對外提供服務的VIP vrrp_instance VI_Master { #指定Keepalived的角色,MASTER為主,BACKUP為備 state MASTER #HA檢測設備 interface eth1 #虛擬路由編號,主備要一致 virtual_router_id 99 #定義優先級,數字越大,優先級越高,主DR必須大於備用DR priority 100 #檢查間隔,默認為1s,VRRP Multicast 廣播周期秒數 advert_int 1 #認證 authentication { auth_type PASS auth_pass 1111 } #定義vip,多個vip可換行添加 virtual_ipaddress { 192.168.200.1 }
#執行發送郵件給global_defs的配置
smtp_alert } #director server 設置 virtual_server 192.168.200.1 3308 { #每隔6秒查看realserver狀態 delay_loop 6 #lvs調度算法 lb_algo wlc #lvs工作模式為DR(直接路由)模式 lb_kind DR #同一IP 的連接50秒內被分配到同一台realserver(測試時建議改為0) persistence_timeout 50 #用TCP監測realserver的狀態 protocol TCP #realserver 設置 real_server 192.168.200.10 3308 { #定義權重 weight 3 TCP_CHECK { #連接超時時間 connect_timeout 3 #重連次數 nb_get_retry 3 #重試的間隔時間 delay_before_retry 3 #連接的后端端口 connect_port 3308 } } real_server 192.168.200.12 3308 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 3308 } } }
② BACKUP Keepalived配置(192.168.200.24,/etc/keepalived/keepalived.conf):
! Configuration File for keepalived #global_defs區域:主要是配置故障發生時的通知對象以及機器標識 global_defs { notification_email { zjy@xxx.com } notification_email_from keepalived@smtp.dxy.cn smtp_server 192.168.200.254 smtp_connect_timeout 30 #設置lvs的id router_id LVS_Masterdata_S } #用來定義對外提供服務的VIP vrrp_instance VI_Slave { #指定Keepalived的角色,MASTER為主,BACKUP為備 state BACKUP #HA檢測設備 interface eth0 #虛擬路由編號,主備要一致 virtual_router_id 99 #定義優先級,數字越大,優先級越高,主DR必須大於備用DR priority 80 #檢查間隔,默認為1s,VRRP Multicast 廣播周期秒數 advert_int 1 #認證 authentication { auth_type PASS auth_pass 1111 } #定義vip,多個vip可換行添加 virtual_ipaddress { 192.168.200.1 }
#執行發送郵件給global_defs的配置
smtp_alert } #director server 設置 virtual_server 192.168.200.1 3308 { #每隔6秒查看realserver狀態 delay_loop 6 #lvs調度算法 lb_algo wlc #lvs工作模式為DR(直接路由)模式 lb_kind DR #同一IP 的連接50秒內被分配到同一台realserver(測試時建議改為0) persistence_timeout 50 #用TCP監測realserver的狀態 protocol TCP #realserver 設置 real_server 192.168.200.10 3308 { #定義權重 weight 3 TCP_CHECK { #連接超時時間 connect_timeout 3 #重連次數 nb_get_retry 3 #重試的間隔時間 delay_before_retry 3 #連接的后端端口 connect_port 3308 } } real_server 192.168.200.12 3308 { weight 1 TCP_CHECK { connect_timeout 3 nb_get_retry 3 delay_before_retry 3 connect_port 3308 } } }
③ 開啟Keepalived
/etc/init.d/keepalived start
主Keepalived上的信息:
#VIP已經綁定 root@LVS-Director:~# ip add 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:64:69:45 brd ff:ff:ff:ff:ff:ff inet 172.16.109.128/24 brd 172.16.109.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe64:6945/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:64:69:4f brd ff:ff:ff:ff:ff:ff inet 192.168.200.2/24 brd 192.168.200.255 scope global eth1 valid_lft forever preferred_lft forever inet 192.168.200.1/32 scope global eth1 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe64:694f/64 scope link valid_lft forever preferred_lft forever #LVS相關信息被自動配置 root@LVS-Director:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.200.1:3308 wlc persistent 50 -> 192.168.200.10:3308 Route 3 0 0 -> 192.168.200.12:3308 Route 1 0 0
備Keepalived的信息:
#VIP沒有被配置, root@LVS-Director2:~# ip add 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 13: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1 link/ether 00:16:3e:24:60:11 brd ff:ff:ff:ff:ff:ff inet 192.168.200.24/24 brd 192.168.200.255 scope global eth0 valid_lft forever preferred_lft forever #LVS相關信息被自動配置 root@LVS-Director2:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.200.1:3308 wlc persistent 50 -> 192.168.200.10:3308 Route 3 0 0 -> 192.168.200.12:3308 Route 1 0 0
director server 已經啟動,然后通過上面的腳本啟動real server。
④ 測試
1,模擬RS1掛了,看LVS是否保證DBProxy的高可用:
1:關閉RS1的DBProxy root@LVS-RS1:/usr/local/mysql-proxy# ./bin/mysql-proxyd masterdata_proxy stop OK: MySQL-Proxy of masterdata_proxy is stopped 2:通過VIP連接DBProxy /Users/jinyizhou [16:07:17] ~$ mysql -usbtest -psbtest -P3308 -h192.168.200.1 ... sbtest@192.168.200.1 : (none) 04:07:18>show databases; +--------------------+ | Database | +--------------------+ | information_schema | | sbtest | +--------------------+ 2 rows in set (0.00 sec) 3:查看LVS狀態 oot@LVS-Director:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.200.1:3308 wlc persistent 50 -> 192.168.200.12:3308 Route 1 1 0 root@LVS-Director:~# ipvsadm -l --stats IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Conns InPkts OutPkts InBytes OutBytes -> RemoteAddress:Port TCP 192.168.200.1:3308 3 91 0 5616 0 -> 192.168.200.12:3308 3 91 0 5616 0
結果:關閉了RS1,服務還可以使用,所有的連接都被轉到了RS2上。LVS保證了RS服務的HA。
2,模擬LVS掛了,看Keepalived是否保證LVS的高可用:
關閉MASTER Keepalived root@LVS-Director:~# /etc/init.d/keepalived stop [ ok ] Stopping keepalived (via systemctl): keepalived.service. VIP漂移了: root@LVS-Director:~# ip add 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:64:69:45 brd ff:ff:ff:ff:ff:ff inet 172.16.109.128/24 brd 172.16.109.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe64:6945/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:64:69:4f brd ff:ff:ff:ff:ff:ff inet 192.168.200.2/24 brd 192.168.200.255 scope global eth1 valid_lft forever preferred_lft forever inet6 fe80::20c:29ff:fe64:694f/64 scope link valid_lft forever preferred_lft forever LVS也關閉了: root@LVS-Director:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn 查看原先的BACKUP Keepalived:接管了VIP root@LVS-Director2:~# ip add 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 13: eth0@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1 link/ether 00:16:3e:24:60:11 brd ff:ff:ff:ff:ff:ff inet 192.168.200.24/24 brd 192.168.200.255 scope global eth0 valid_lft forever preferred_lft forever inet 192.168.200.1/32 scope global eth0 valid_lft forever preferred_lft forever LVS正常: root@rLVS-Director2:~# ipvsadm -ln IP Virtual Server version 1.2.1 (size=4096) Prot LocalAddress:Port Scheduler Flags -> RemoteAddress:Port Forward Weight ActiveConn InActConn TCP 192.168.200.1:3308 wlc persistent 50 -> 192.168.200.10:3308 Route 3 1 0 -> 192.168.200.12:3308 Route 1 0 0 日志信息:切換成了MASTER Apr 24 16:16:14 LVS-Director2 Keepalived_vrrp[41092]: VRRP_Instance(VI_1) Transition to MASTER STATE Apr 24 16:16:15 LVS-Director2 Keepalived_vrrp[41092]: VRRP_Instance(VI_1) Entering MASTER STATE 連接DBProxy:正常 /Users/jinyizhou [16:26:13] ~$ mysql -usbtest -psbtest -P3308 -h192.168.200.1 ... sbtest@192.168.200.1 : sbtest 04:26:16>select * from x; ...
結果:關閉了MASTER Keepalived,服務還可以使用,所有的連接都被轉到了BACKUP Keepalived上。Keepalived保證了LVS服務的HA。在使用Keepalived中,在vrrp_script的區域里定義腳本名字和腳本執行的間隔和腳本執行的優先級,在然后在實例(vrrp_instance區域里)引用。通過腳本做一些相關操作:郵件發送、數據操作等。如下面的配置樣本:

vrrp_script vs_mysql_82 { script "/etc/keepalived/checkMySQL.py -h 127.0.0.1 -P 3309" interval 15 } vrrp_instance VI_82 { state backup nopreempt interface eth1 virtual_router_id 82 priority 100 advert_int 5 authentication { auth_type PASS auth_pass 1111 } track_script { vs_mysql_82 } notify /etc/keepalived/notify.py virtual_ipaddress { 192.168.11.110 } }
關於Keepalived的詳細說明可以看官網或則http://www.cnblogs.com/pricks/p/3822232.html。到此,關於整個LVS+Keepalived+DBProxy已經介紹完畢,解決了美團點評DBProxy讀寫分離使用說明指出的第二個問題,實現了完整意義上的高可用。最后數據庫的架構如下:MGW可以當成LVS,通過Keepalived來實現HA,最終實現跨機房讀寫分離。如下圖所示的架構:
性能測試說明
通過上面的說明,大致清楚了數據庫的訪問方式:先讀取LVS提供的虛擬IP,根據其工作模式和調度算法連接到DBProxy,再通過DBProxy其工作方式進行轉發,這樣多了幾層連接,對數據庫的性能有多大影響?現在通過美團點評DBProxy讀寫分離使用說明中的測試方法進行測試:
直連數據庫:
./bin/sysbench --test=./share/sysbench/oltp_read_write.lua --mysql-host=192.168.200.202 --mysql-port=3306 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=120 --threads=8 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 prepare/run/cleanup
直連DBProxy:
./bin/sysbench --test=./share/sysbench/oltp_read_write.lua --mysql-host=192.168.200.10 --mysql-port=3308 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=120 --threads=8 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 prepare/run/cleanup
通過LVS:
./bin/sysbench --test=./share/sysbench/oltp_read_write.lua --mysql-host=192.168.200.1 --mysql-port=3308 --mysql-user=sbtest --mysql-password=sbtest --mysql-db=sbtest --report-interval=10 --max-requests=0 --time=120 --threads=8 --tables=3 --table-size=500000 --skip-trx=on --db-ps-mode=disable --mysql-ignore-errors=1062 prepare/run/cleanup
通過對8,16個線程的測試,發現通過LVS比直接DBProxy的QPS有近5%的提升。雖然訪問數據庫的鏈路加長了,但是通過LVS實現了負載均衡,使得多個DBproxy一起工作,提高了效率,性能沒有比直連DBProxy差。當然,直連數據庫的性能還是最高的。可以看美團點評DBProxy讀寫分離使用說明的性能測試說明。
總結:
通過這篇文章和美團點評DBProxy讀寫分離使用說明的一些基本介紹,了解了DBProxy讀寫分離功能的使用、性能和高可用的相關說明。關於更多DBProxy的說明可以參考手冊說明。
相關文檔