在网络系统中,除了用负载均衡来提高性能和可用性外,还有大量的主从备份模式应用,比如当前版本的 redis 和 mongodb。我们有无数的理由希望备份服务器能在合适的时间自动接替 “受伤倒地” 的主服务器继续完成后续工作,也就是所谓的 “热切换”。在 Linux 上要实现这个非常简单,几行命令就搞定了。
其原理就是动态绑定虚拟IP(或漂移IP)。假设主服务器 192.168.1.20,备份服务器 192.168.1.30,虚拟 IP 为 192.168.1.5。我们首先在主服务器上运行如下脚本。
$ cat master.sh
#!/bin/bash
ifconfig eth0:1 192.168.1.5 broadcast 192.168.1.255 netmask 255.255.255.0 up
route add -host 192.168.1.5 dev eth0:1
arping -I eth0 -c 3 -s 192.168.1.5 192.168.1.1
$ sudo ./master.sh
ARPING 192.168.1.1 from 192.168.1.5 eth0
Unicast reply from 192.168.1.1 [00:1F:A3:2C:E2:38] 1.627ms
Unicast reply from 192.168.1.1 [00:1F:A3:2C:E2:38] 0.989ms
Unicast reply from 192.168.1.1 [00:1F:A3:2C:E2:38] 0.968ms
Sent 3 probes (1 broadcast(s))
Received 3 response(s)
很显然上级路由(192.168.1.1)已经接受了我们的设置,用 ifconfig 可以查看虚拟 IP 的绑定信息。
$ cat a.txt
eth0 Link encap:Ethernet HWaddr 00:0c:29:04:a0:db
inet addr:192.168.1.20 Bcast:192.168.1.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:fe04:a0db/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:238 errors:0 dropped:0 overruns:0 frame:0
TX packets:188 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:25793 (25.7 KB) TX bytes:25405 (25.4 KB)
eth0:1 Link encap:Ethernet HWaddr 00:0c:29:04:a0:db
inet addr:192.168.1.5 Bcast:192.168.1.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
如此就将 192.168.1.5 绑定到主服务器上,相关用户就可以通过该虚拟IP访问主服务器服务了。
$ ssh 192.168.1.5
接着,我们在备份服务器(192.168.1.30)上运行监控脚本 (实际部署时可以作为后台进程运行,并将输出重定向到 /dev/null)。
$ cat slave.sh
#!/bin/bash
while true
do
ping -c 3 192.168.1.20
if [ $? -eq 0 ]; then
echo “Master Server running …”
sleep 5
else
echo “Backup Server running …”
ifconfig eth0:1 192.168.1.5 broadcast 192.168.1.255 netmask 255.255.255.0 up
route add -host 192.168.1.5 dev eth0:1
arping -I eth0 -c 3 -s 192.168.1.5 192.168.1.1
break
fi
done
该脚本通过循环 ping 主服务器(192.168.1.20)的返回值来判断主服务器是否完蛋,当然也可以用诸如 wget + grep 的方式监控 WebServer 等。一旦发现主服务器异常将发送虚拟 IP 绑定设置,如此来实现将 192.168.1.5 的请求路由到备份服务器 192.168.1.30 上来。
开始运行监控脚本。
$ sudo ./slave.sh
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=1.01 ms
64 bytes from 192.168.1.20: icmp_seq=2 ttl=64 time=0.855 ms
64 bytes from 192.168.1.20: icmp_seq=3 ttl=64 time=0.813 ms
— 192.168.1.20 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.813/0.893/1.011/0.085 ms
Master Server running …
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=1 ttl=64 time=0.989 ms
64 bytes from 192.168.1.20: icmp_seq=2 ttl=64 time=0.887 ms
64 bytes from 192.168.1.20: icmp_seq=3 ttl=64 time=0.813 ms
— 192.168.1.20 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 2004ms
rtt min/avg/max/mdev = 0.813/0.896/0.989/0.076 ms
Master Server running …
现在我们关掉主服务器(拔网线比关电源要好些),备份服务器将开始接管。
— 192.168.1.20 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.518/0.724/0.829/0.145 ms
Master Server running …
PING 192.168.1.20 (192.168.1.20) 56(84) bytes of data.
— 192.168.1.20 ping statistics —
3 packets transmitted, 0 received, 100% packet loss, time 2004ms
Backup Server running …
ARPING 192.168.1.1 from 192.168.1.5 eth0
Unicast reply from 192.168.1.1 [00:1F:A3:2C:E2:38] 1.812ms
Unicast reply from 192.168.1.1 [00:1F:A3:2C:E2:38] 1.110ms
Unicast reply from 192.168.1.1 [00:1F:A3:2C:E2:38] 1.116ms
Sent 3 probes (1 broadcast(s))
Received 3 response(s)
这个时候,我们再次访问 192.168.1.5 的服务时就会自动导向备份服务器 192.168.1.30 上。
等主服务器 “修好” 以后,再次运行 “sudo ./master.sh” 即可恢复。
附: 使用 down 参数可以解除虚拟IP的绑定。
$ sudo ifconfig eth0:1 192.168.1.5 broadcast 192.168.1.255 netmask 255.255.255.0 down
——— 分隔线 —————
此种做法当然远不如专业级的 heartbeat、keepalived,但胜在简单易用。