分布式 高可用(Keepalived/HAProxy)
简介:高可用(High Avalilability)指两台或两台以上业务系统启动着相同的服务,如果其中一台有故障,另外一台自动接管工作,实现故障转移。
一、Keepalived
简介:Keepalived是服务器一种高性能且轻量级的高可用或热备解决方案,通过VRRP协议(虚拟路由冗余协议)来防止服务器静态路由单点故障的发生,结合Nginx可以实现WEB前端服务的高可用。
1. 基础
A. 用途
故障转移:实现负载均衡中MASTER主机BACKUP主机之间的故障转移和自动切换;
心跳检测:负载均衡定期检查RS服务器的可用性决定是否给其分发请求;
B. VRRP(Vritrual Router Redundancy Protocol)协议:是一种容错协议,为了解决静态路由的单点故障;是通过一种竞选协议机制来将路由任务交给某台VRRP路由器,通过优先级来确定MASTER和BACKUP;保证当主机的下一条路由器出现故障时,由另一台路由器来替代出现故障的路由器进行工作,从而保证网络通信的连续性和可靠性,而且自身使用了加密协议;
C. 故障切换转移原理:在Keepalived正常工作时,MASTER节点会不断的向BACKUP节点发送心跳消息,用来告诉BACKUP节点自己还活着,当MASTER节点发生故障时,BACKUP节点就无法继续检测到MASTER节点的心跳,进而调用自身的接管程序,接管MASTER节点的IP资源和服务,当MASTER节点恢复故障时,BACKUP节点会释放MASTER节点故障时自身接管的IP资源和服务,恢复到原来的自身的备用角色;
D. 工作方式分类
抢占式(默认模式):MASTER以组播方式不断的向虚拟路由器组内发送自己的心跳报文,一旦BACKUP在设定时间内没有收到心跳信息的次数超过了限定次数,则会将MASTER的所有权转移到优先级最高的BACKUP;
非抢占模式:指只有在主节点完全故障时才能将BACKUP变为MASTER。
2. Keepalived搭建
A. 安装keepalived:yum install keepalived -y;
B. 修改/etc/keepalived/keepalived.conf配置文件,注意主备文件的区别在于router_id信息不一致、state状态描述信息不一致、priority优先级不一致;
C. 启动keepalived:systemctl start keepalived;
D. 查看日志:默认日志文件是var/log/messages;
E. 查看虚拟IP状态:ip a;
F. 测试nginx高可用
nginx01和nginx02主机都正常开启,nginx01主机上keepalived为主,nginx02主机上keepalived为备,keepalived也都正常开启,访问http://10.12.113.88,正常返回nginx01主机上的内容;
nginx01和nginx02主机都正常开启,nginx01主机上keepalived为主,但keepalived服务关闭,nginx02主机上keepalived为备且服务正常开启,访问http://10.12.113.88,正常返回nginx02主机上的内容;
3. keepalived.conf 配置文件
! Configuration File for keepalived global_defs { # 本节点的标识信息,即hostname router_id dcy01 } # 定时执行脚本并对脚本执行的结果进行分析,动态调整vrrp_instance的优先级 vrrp_script nginx_check { # 检测Nginx状态的脚本路径 script "/etc/keepalived/nginx_check.sh" # 检测时间间隔 interval 5 } # 定义虚拟路由,VI_1为虚拟路由的自定义标示符 vrrp_instance VI_1 { # 主节点为MASTER, 对应的备份节点为BACKUP state MASTER # 绑定虚拟IP的网络接口,与本机IP地址所在的网络接口相同 interface ens33 # 虚拟路由的ID号,两个节点设置必须一样,可选IP最后一段使用,相同的VRID为一个组,是决定多播的MAC地址 virtual_router_id 1 # 节点优先级,值范围 0-254,优先级高的就是主节点 priority 100
# 当转换为MASTER状态时,延迟多少秒发送第二组的免费ARP。默认为5s,0表示不发送第二组免的免费ARP
vrrp_garp_master_delay 10
# 当转换为MASTER状态时,在一组中一次发送的免费ARP数量。默认是5
vrrp_garp_master_repeat 10 # 组播信息发送间隔,两个节点设置必须一样,默认1s advert_int 1 # 设置验证信息,两个节点必须一致 authentication { # 认证方式 auth_type PASS # 密码 auth_pass 123456 } # 虚拟IP池,两个节点设置必须一样 virtual_ipaddress { # 虚拟ip,可以定义多个,默认32位 mask 192.168.1.1 } track_script { # 执行Nginx监控 nginx_check }
# 当当前节点成为master时,通知脚本执行任务
notify_master "/rhxy/keepalived/script/slave-to-master.sh"
# 当当前节点成为backup时,通知脚本执行任务
notify_backup "/rhxy/keepalived/script/master-to-slave.sh"
# 当当前节点出现故障,执行的任务
notify_fault "/rhxy/keepalived/script/master-to-slave.sh"
# 设置keepalived的状态,传入这个脚本的参数为($1为GROUP或INSTANCE、
$2为组名或实例名、
$3为"MASTER"|"BACKUP"|"FAULT"
)
notify "/rhxy/keepalived/script/notify-state.sh"
}
4. keepalived脑裂现象
A. 现象:脑裂指由于某些原因(如网络差、防火墙开启等),导致多台keepalived的服务器在指定时间内无法检测到对方存活心跳信息(事实上服务器还是存活状态),从而导致相互抢占对方的资源和服务所有权的现象;
B. keepalived监控nginx:Nginx宕机会导致用户请求失败,但是keepalived不会进行切换,故需要编写检测nginx是否存活的脚本,shell脚本如下;
#!/bin/sh
# 判断nginx是否关闭 if [ `ps -C nginx --no-header | wc -l` -eq 0 ];then #systemctl stop keepalived pkill keepalived fi
5. 主备切换时间原理
A. 将自身设置为MASTER节点后,立刻发送GARP广播包,默认发送两次,每次发送5个GARP数据包,每次间隔5s,GARP数据包中包含自身的优先级和工作状况数据,BACKUP服务器通过接收到的VRRP报文的情况判断MASTER路由器是否正常工作;
B. MASTER路由器主动放弃MASTER地位时,会先发送优先级为0的VRRP报文,使BACKUP路由器快速切换变为MASTER路由器,切换时间Skew_Time=(256 - BACUP路由器的优先级) / 256 秒;
C. MSTER路由器因故障不能发送VRRP报文时,BACKUP路由器并不能立即知道其工作状况,当BACKUP路由器等待一段时间后,如果还没接收到VRRP报文,那么会认为MASTER路由器无法正常工作,而把自己升级为MASTER路由器,周期性发送报文,如果此时多个BACKUP路由器竞争MASTER路由器的位置,将通过优先级来选举MASTER路由器,BACKUP路由器默认等待时间称为Master_Down_Interval=(3 * advert_int)+ Skew_Time;
D. 在性能不够稳定的网络中,Backup路由器可能因为网络堵塞而在Master_Down_Interval期间没有收到Master路由器的报文而主动抢占为Master位置,如果此时原Master路由器的报文又到达了,就会出现虚拟路由器的成员频繁的进行Master抢占现象,为了缓解这种现象的发生,特制定了延迟等待定时器(preempt_delay:设置抢占延迟。单位是秒,范围是0---1000,默认是0.发现低优先级的MASTER后多少秒开始抢占),它可以使得Backup路由器在等待了Master_Down_Interval后,再等待延迟等待时间,如在此期间仍然没有收到VRRP报文,此时Backup路由器才会切换为Master路由器,对外发送VRRP报文.
6. 其他
A. Keepalived防火墙策略:防火墙规则主从机器都要配置,双向打开vrrp服务,firewall-cmd --permanent --add-protocol=vrrp;firewall-cmd --reload;
B. 常见问题
问题一:WARNING - script '/etc/keepalived/nginx_check.sh' is not executable for uid:gid 0:0 - disabling;
原因:keepalived上监控脚本没有执行权限;
解决方案:chomd +x /etc/keepalived/nginx_check.sh。
C. 服务莫名不能启动:比如找不到配置文件,子进程无法启动等,可以执行:sed -i 's/^SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config && reboot;
二、HAProxy
简介:HAProxy提供高可用、负载均衡以及反向代理服务,支持虚拟主机,是免费、快速并且可靠的一种解决方案。
1. 基础
A. 特性
基于TCP(第四层)和HTTP(第七层)应用的代理,特别适合负载大的WEB站点,保护WEB服务器不会暴露在公网上;
是一种单进程、事件驱动模型,支持非常大的并发连接数;
拥有服务器健康检查功能和系统状态监控页面,当代理服务出现故障会自动剔除,可以减少程序增加健康检测功能,如果恢复又重新加入进来;
B. 负载均衡客户端与服务器识别方式
用户IP识别;
cookie识别;
session识别;
C. 负载均衡算法
roundrobin(默认算法):轮询算法,根据权重进行服务器轮流使用,适合短连接场景;
leastconn:最近最少算法,使用最近最少使用的服务器,适合长连接场景;
source:哈希算法,对请求源IP地址进行哈希。
D. http协议健康检查方式
option httpchk:通过监听端口进行健康检查,注意haproxy只会去检查后端server的端口,并不能保证服务的真正可用;
option httpchk GET /index.html:通过URI获取进行健康检测,这是用发送GET请求到后端的WEB界面,基本上可以代表后端服务的可用性;
option httpchk HEAD /index.jsp HTTP/1.1\r\nHost:\ www.xxx.com:通过request获取的头部信息进行匹配进行健康检测,这种检测方式,则是基于高级,精细的一些监测需求,通过对后端服务访问的头部信息进行匹配检测;
2. HAProxy搭建
A. 安装haproxy:yum install haproxy -y;
B. 修改/etc/haproxy/haproxy.cfg配置文件;
C. 启动haproxy:systemctl start haproxy;
D. 访问haproxy监控平台:http://127.0.0.1:1080。
3. haproxy.cfg 配置文件
# 全局参数 global # 日志配置,指定使用127.0.0.1上的syslog服务中的local0日志设备,记录日志等级为info的日志 log 127.0.0.1 local0 info # 设置运行haproxy的用户,可以使用uid替代 user haproxy # 设置运行haproxy的组,可使用gid替代 group haproxy # 以守护进程的方式运行 daemon # 启动时的进程数,设置多个有助提高处理效率,但是过多的进程数也可能会导致进程的崩溃 nbproc 16 # 每个进程的最大连接数 ,由于每个连接包括一个客户端和一个服务器端,所以单个进程的TCP会话最大数目将是该值的两倍 maxconn 4096 # 设置最大打开的文件描述符数,在1.4的官方文档中提示,该值会自动计算,所以不建议进行设置 #ulimit -n 65536 # 将所有进程写入pid文件 pidfile /var/run/haproxy.pid # 默认参数 defaults # 运行模式有http、tcp(默认值)、health mode http # 使用127.0.0.1上的syslog服务的local3设备记录错误信息 log 127.0.0.1 local3 err # 定义连接后端服务器的失败重连次数,判断服务不可用 retries 3 # 启用HTTP请求日志记录,默认haproxy日志格式很简单 option httplog # 如果后端有服务器宕机,强制切换到正常服务器 option redispatch # 丢弃由于客户端等待时间过长而关闭连接但还在harpoxy等待队列中的请求 option abortonclose # 不记录健康检查的日志信息 option dontlognull # 每次请求完毕后主动关闭http通道 option http-server-close # 连接超时 contimeout 5000 # 客户端超时 clitimeout 3000 # 服务器超时 srvtimeout 3000 # frontend和backend的组合体,定义一个名为status的部分 listen status # 定义监听的套接字 bind 0.0.0.0:1080 # 定义为HTTP模式 mode http # 继承global中log的定义 log global # stats是haproxy的一个统计页面的套接字,该参数设置统计页面的刷新间隔为30s stats refresh 30s # 统计页面URL路径 stats uri /admin-stats # 设置统计页面认证时的提示内容 stats realm Private lands # 设置统计页面认证的用户和密码,如果要设置多个,另起一行写入即可 stats auth admin:123456 # 隐藏统计页面上的haproxy版本信息 stats hide-version # 接收请求的前端虚拟节点 frontend web # 监听80端口 bind 0.0.0.0:80 # 定义为HTTP模式 mode http # 启用X-Forwarded-For,在requests头部插入客户端IP发送给后端的server,使后端server获取到客户端的真实IP option forwardfor # 定义一个名叫static_down的acl,当backend static_sever中存活机器数小于1时会被匹配到 acl static_down nbsrv(static_server) lt 1 # 定义一个名叫php_web的acl,当请求的url末尾是以.php结尾的,将会被匹配到,上面两种写法任选其一 acl php_web url_reg /*.php$ # 定义一个名叫static_web的acl,当请求的url末尾是以.css、.jpg、.png、.jpeg、.js、.gif结尾的,将会被匹配到,上面两种写法任选其一 acl static_web url_reg /*.(css|jpg|png|jpeg|js|gif)$ # 如果满足策略static_down时,就将请求交予backend web_server use_backend web_server if static_down # 如果满足策略php_web时,就将请求交予backend web_server use_backend web_server if php_web # 如果满足策略static_web时,就将请求交予backend static_server use_backend static_server if static_web # 配置后端服务集群 backend web_server # 设置为http模式 mode http # 设置haproxy的调度算法为源地址hash balance source # 允许向cookie插入SERVERID,每台服务器的SERVERID可在下面使用cookie关键字定义 cookie SERVERID # 开启对后端服务器的健康检测,通过GET /test/index.php来判断后端服务器的健康情况 option httpchk GET /test/index.php server php_server_1 10.12.25.68:80 cookie 1 check inter 2000 rise 3 fall 3 weight 2 server php_server_2 10.12.25.72:80 cookie 2 check inter 2000 rise 3 fall 3 weight 1 # server语法:server <name> <address>[:port] [param*] # 使用server关键字来设置后端服务器;为后端服务器所设置的内部名称[php_server_1],该名称将会呈现在日志或警报中、后端服务器的IP地址,支持端口映射[10.12.25.68:80]、指定该服务器的SERVERID为1[cookie 1]、接受健康监测[check]、监测的间隔时长,单位毫秒[inter 2000]、监测正常多少次后被认为后端服务器是可用的[rise 3]、监测失败多少次后被认为后端服务器是不可用的[fall 3]、分发的权重[weight 2]、最后为备份用的后端服务器,当正常的服务器全部都宕机后,才会启用备份服务器[backup] server php_server_bak 10.12.25.79:80 cookie 3 check inter 1500 rise 3 fall 3 backup backend static_server mode http option httpchk GET /test/index.html server static_server_1 10.12.25.83:80 cookie 3 check inter 2000 rise 3 fall
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗