linux

high availability cluster for spring boot with keepalived and nginx

nginx 可以很好的实现负载均衡和高可用,但如果运行 nginx 的服务器宕机,或者 nginx 本身崩溃,服务同样将不可用。此时,keepalived 就派上了用场,keepalived 实现高可用主要依赖 虚拟IP,即VIP,通过 IP 漂移实现服务的高可用。如果不了解 虚拟IP 和 IP 漂移,那么你会一头雾水,下面,我简单的解释下吧。

虚拟 IP 与 ARP 协议

所谓 虚拟IP,其实和真实 IP 没区别,你可以理解为没有实际分配给某台主机的 IP,以太网中,MAC 地址才是数据传输时用的物理地址,IP 地址只是逻辑地址,可以理解为,通过 IP 地址获取到 MAC 地址,然后与 MAC 地址对应的主机进行数据的传输,将 IP地址 解析为 MAC 地址是由 ARP(地址解析协议,全称 Address Resolution Protocol) 完成的,正常情况下,一个 IP 分配给一个 MAC 地址对应的物理设备,而虚拟 IP 则没有固定的分配给某个物理设备。

IP 地址漂移的细节

当使用 keepalived 时,keepalived 需要你提供一个 VIP,即虚拟 IP 地址,之后它会发送一个 ARP 包,告诉所有主机这个 IP 地址对应的 MAC 地址就是当前设备的 MAC 地址,此时,当前设备等于有两个 IP 地址,一个是真实分配给它的,一个是虚拟的,无论通过那个地址访问,最后解析到的 MAC 地址都是它,当这台服务器宕机时,备用服务器监测不到心跳,则会发送一个 ARP 包,告诉网络中的所有主机,这个 IP 对应的 MAC 地址是它,此后,所有发到这个虚拟 IP 的请求将发给备用机,当之前的服务器恢复,则可能(主要看配置)会发送 ARP 包,将虚拟 IP 绑定到主服务器。虚拟 IP 在主服务器和备用服务器间的切换称之为 IP 漂移。

当明白了 虚拟IP 和 IP 漂移技术后,keepalived 实现高可用的原理就很简单了,下面是 keepalived 的一段配置:

vrrp_script check_java {
    script "pgrep java"
    interval 2
}

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 13
    priority 200
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass letmein
    }
    
    virtual_ipaddress {
        172.27.1.13/24 dev eth0
    }

    track_script {
        check_java
    }
}

vrrp_instance VI_2 {
    state BACKUP
    interface eth0
    virtual_router_id 14
    priority 101
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass letmein
    }
    
    virtual_ipaddress {
        172.27.1.14/24 dev eth0
    }

    track_script {
        check_java
    }
}

这里,我们从 中间这段配置开始说起:

vrrp_instance VI_1 {
    state MASTER
    interface eth0
    virtual_router_id 13
    priority 200
    advert_int 1
    
    authentication {
        auth_type PASS
        auth_pass letmein
    }
    
    virtual_ipaddress {
        172.27.1.13/24 dev eth0
    }

    track_script {
        check_java
    }
}

vrrp_instance VI_1 定义了一个 虚拟 IP VI_1,state MASTER 表示 当前服务器是 master 节点,即主服务器,备用服务器用 BACKUP,均为大写。后面的 virtual_router_id 可以是随机数字,但是对于同一个 虚拟IP 主节点和 备用节点这个数字必须一致,后面的 priority 200 是指优先级,在 IP 漂移时 按优先级从大到小 漂移,advert_int 1 是检查间隔,这里是 1秒,后面是认证以及 虚拟 IP 的配置,最后是检查时调用的脚本,即每隔一秒调用这个脚本去检查,各个节点间,这个值建议一致,我们现在看这个脚本。

vrrp_script check_java {
    script "pgrep java"
    interval 2
}

这里,脚本的名称是 check_java,如果 java 这个进程存在,则正常,否则会发生 IP 漂移。你可能也看到了,在我的配置文件里,可不止一个 虚拟 IP,为什么呢?

高可用与高并发

你可能已经注意到了,keepalived 虽然实现了高可用,但是 IP 漂移到主服务器,这意味着对外提供服务的只有主服务器,从服务器一直在等主服务器挂了,挂了虚拟IP就漂移到从服务器了,之后从服务器就可以对外提供服务了。这样子,是不是有点浪费呢?而解决这种浪费的办法就是互为主从,假设有A、B两台服务器,有V1、V2两个虚拟 IP,V1 漂移到 A,A为主服务器,B为从服务器,V2 漂移到B,B为主服务器,A为从服务器,当 A宕机,两个 IP 都漂移到 B,如果 B 也宕机,整个系统宕机,如果 B 宕机,A 正常,则两个IP都漂移到A,如果这里的 V1 和 V2 均为内网地址,然后你使用 六个公网地址 + 三台服务器 + nginx 实现了 nginx 的主备切换,此时,内网里的应用 A 和 B 可以同时工作,实现了高可用与高并发,三个虚拟IP可以通过DNS解析给联通、电信、移动用户,且互为主备,不仅高可用,而且还高并发。

梦想是美好的,现实却很残酷,阿里云,似乎并不支持 keepalived,涉及 ARP 欺骗,具体细节没有研究,腾讯云似乎是支持的,这块没有深入,比较不属于技术范畴了。受限于篇幅,本文就此结束,之后再补充 keepalived 系列文章,比如 keepalived 日志追踪,以及 使用 docker + keepalived + nginx 实现高可用与高并发。

full-stack-trip

Share
Published by
full-stack-trip

Recent Posts

Android 自定义 View 入门

说来惭愧,工作数年,连基本的自…

4 年 ago

retrofit 同时支持 xml 和 json

retrofit 解析 jso…

4 年 ago

mysql - 存储过程 从入门到放弃

最近有个报表的需求,于是乎用了…

4 年 ago

奶嘴战略 - 你不得不知道的扎心真相(一)

一句:英雄枯骨无人问,戏子家事…

4 年 ago

acme.sh 的简单使用

acme.sh 是纯 shel…

4 年 ago

wrk -更现代化的http压测工具

wrk 是一款更现代化的 ht…

4 年 ago