基于 HAProxy + Keepalived 搭建 RabbitMQ 高可用集群
RabbitMQ 集群
通常情况下,在集群中我们把每一个服务称之为一个节点,在 RabbitMQ 集群中,节点类型可以分为两种:
- 内存节点:元数据存放于内存中。为了重启后能同步数据,内存节点会将磁盘节点的地址存放于磁盘之中,除此之外,如果消息被持久化了也会存放于磁盘之中,因为内存节点读写速度快,一般客户端会连接内存节点。
- 磁盘节点:元数据存放于磁盘中(默认节点类型),需要保证至少一个磁盘节点,否则一旦宕机,无法恢复数据,从而也就无法达到集群的高可用目的。
PS:元数据,指的是包括队列名字属性、交换机的类型名字属性、绑定信息、vhost等基础信息,不包括队列中的消息数据。
RabbitMQ 中的集群主要有两种模式:普通集群模式和镜像队列模式。
普通集群模式
在普通集群模式下,集群中各个节点之间只会相互同步元数据,也就是说,消息数据不会被同步。那么问题就来了,假如我们连接到 A 节点,但是消息又存储在 B 节点又怎么办呢?
不论是生产者还是消费者,假如连接到的节点上没有存储队列数据,那么内部会将其转发到存储队列数据的节点上进行存储。虽然说内部可以实现转发,但是因为消息仅仅只是存储在一个节点,那么假如这节点挂了,消息是不是就没有了?因此这种普通集群模式并没有达到高可用的目的。
镜像队列模式
普通集群模式下不同节点之间只会相互同步元数据(交换机、队列、绑定关系、vhost的定义)而不会同步消息。例如,队列 1 的消息只存储在节点 1 上,节点 2 和节点 3只 同步了交换机和队列的元数据,但是没有同步消息。
假如生产者连接的是节点 3,要将消息通过交换机A路由到队列 1,最终消息还是会转发到节点 1 上存储;同理如果消费者连接的是节点 2,要从队列 1 上拉取消息,最终消息会从节点1转发到节点 2,其它节点起到一个路由的作用;如果节点1挂掉,则队列 1 的全部数据就会丢失。
镜像队列模式下,节点之间不仅仅会同步元数据,消息内容也会在镜像节点间同步,可用性更高。这种方案提升可用性的同时,也会因为同步数据带来的网络开销从而在一定程度上影响到性能。
基于 HAProxy + Keepalived 高可用集群
假如一个 RabbitMQ 集群中,有多个内存节点,我们应该连接到哪一个节点呢?这个选择的策略如果放在客户端做,那么会有很大的弊端,最严重的的就是每次扩展集群都要修改客户端代码,所以这种方式并不是很可取,所以我们在部署集群的时候就需要一个中间代理组件,这个组件要能够实现服务监控和转发,比如 Redis 中的 Sentinel(哨兵)集群模式,哨兵就可以监听 Redis 节点并实现故障转移。
在 RabbitMQ 集群中,通过 Keepalived 和 HAProxy 两个组件实现了集群的高可用性和负载均衡功能。
HAProxy
HAProxy 是一个开源的、高性能的负载均衡软件,同样可以作为负载均衡软件的还有 nginx,lvs 等。 HAproxy 支持 7 层负载均衡和 4 层负载均衡。
负载均衡
所谓的 7 层负载均衡和 4 层负载均衡针对的是 OSI 模型而言,如下图所示就是一个 OSI 通信模型:
| 7蹭 | 应用层 | 应用层 HTTP、FTP、DNS、URI、HTML、TLS/SSL、SMTP、POP、IMAP、TELNET、SSH | 应用程序 |
| 6层 | 表示层 | ||
| 5层 | 会话层 | ||
| 4层 | 传输层 | 传输层 TCP、UDP、SCTP、DCCP | 操作系统 |
| 3层 | 网络层 | 网络层 ARP、IP、ICMP、RIP | |
| 2层 | 数据链路层 | 网络接口层 | 设备驱动程序网络接口 |
| 1层 | 物理层 |
上图中看到,第 7 层对应了应用层,第 4 层对应了传输层。常用的负载均衡软件如 nginx 一般工作在第 7 层,lvs(Linux Virtual Server)一般工作在第 4 层。
4层负载:
4 层负载使用了 NAT (Network Address Translation)技术,即:网络地址转换。收到客户端请求时,可以通过修改数据包里的源 IP 和端口,然后把数据包转发到对应的目标服务器。4 层负载均衡只能根据报文中目标地址和源地址对请求进行转发,无法判断或者修改请求资源的具体类型。
7层负载:
根据客户端请求的资源路径,转发到不同的目标服务器。
高可用 HAProxy
HAProxy 虽然实现了负载均衡,但是假如只是部署一个 HAProxy,那么其本身也存在宕机的风险。一旦 HAProxy 宕机,那么就会导致整个集群不可用,所以我们也需要对 HAProxy 也实现集群,那么假如 HAProxy 也实现了集群,客户端应该连接哪一台服务呢?问题似乎又回到了起点,陷入了无限循环中...
Keepalived
为了实现 HAProxy 的高可用,需要再引入一个 Keepalived 组件,Keepalived 组件主要有以下特性:
- 具有负载功能,可监控集群中的节点状态,如果集群中某一个节点宕机,可以实现故障转移。
- 其本身也可以实现集群,但是只能有一个
master节点。 master节点会对外提供一个虚拟IP,应用端只需要连接这一个IP就行了。可以理解为集群中的HAProxy节点会同时争抢这个虚拟IP,哪个节点争抢到,就由哪个节点来提供服务。
VRRP 协议
VRRP 协议即虚拟路由冗余协议(Virtual Router Redundancy Protocol)。Keepalived 中提供的虚拟 IP 机制就属于 VRRP,它是为了避免路由器出现单点故障的一种容错协议。
搭建高可用 RabbitMQ 集群
集群环境准备
准备三台虚拟机,分别安装好 Erlang 和 RabbitMQ,可以用克隆功能。
本文服务器环境:CentOS7
[CentOS7] Install RabbitMQ Using PackageCloud Yum Repository
服务器 A:192.168.189.156 RabbitMQ 内存节点 HAPRoxy Keepalived(master)
服务器 B:192.168.189.157 RabbitMQ 内存节点 HAPRoxy Keepalived(backup)
服务器 C:192.168.189.158 RabbitMQ 磁盘节点
Keepalived: Virtual IP 192.168.189.159
集群网络架构
RabbitMQ 环境变量
环境变量配置文件 rabbitmq-env.conf 默认配置在 /etc/rabbitmq 目录,如果不存在直接创建即可,RabbitMQ 应用会自动加载。rabbitmq-env.conf 包含重写 RabbitMQ 脚本和 CLI 工具中内置默认值的环境变量。
该文件由系统 shell 解释,因此应包含一系列 shell 环境变量定义。允许使用普通的shell语法(因为文件的源代码是使用shell “.” 运算符),包括以#号开头的行注解。
按照优先级顺序,启动脚本从 shell 环境变量、rabbitmq-env.conf 和最后从内置的默认值获取它们的值。例如,对于 RABBITMQ_NODENAME 设置,首先检查 shell 环境变量中的RABBITMQ_NODENAME 如果不存在或等于空字符串,则选中 rabbitmq-env.conf 中的 NODENAME;如果它也不存在或等于空字符串,则使用启动脚本中的默认值。
rabbitmq-env.conf 中的变量名始终等于环境变量名,去掉了 RABBITMQ_ 前缀;环境变量中的 RABBITMQ_NODE_PORT 在 rabbitmq-env.conf 中的名字是 NODE_PORT。
RabbitMQ 节点
RabbitMQ 节点以节点名称作为标识,而节点名称由两部分组成:前缀 (默认是rabbit) 和主机名。当节点启动时,它会检查是否已为其分配了节点名,如果配置文件 rabbitmq-env.conf 中没有配置,则节点将解析其主机名并在其前面添加 rabbit 作为其节点名。
如果在给定的主机上运行多个节点,它们必须使用不同的前缀,例如:rabbit1@hostname 和 rabbit2@hostname。如果系统使用完全限定域名作为主机名,RabbitMQ 节点和 CLI 工具必须配置为使用长节点名称。对于服务器节点,需要将 RABBITMQ_USE_LONGNAME 环境变量设置为 true;对于 CLI 工具,必须设置 RABBITMQ_USE_LONGNAME 或 指定 –longnames 选项。例如:rabbit@centos.qq.com 其中 rabbit 为前缀,centos 是主机名,qq.com 为节点的域名。
在集群中节点名称必须是唯一的,每个节点使用节点名称来标识和联系彼此,这意味着必须解析每个节点名的主机名部分。RabbitMQ 默认节点名称是 rabbit@主机名 ,如果想自定义节点名称则需要在配置文件 /etc/rabbitmq/rabbitmq-env.conf 中配置:
NODENAME=rabbit@节点名
配置 .erlang.cookie
.erlang.cookie 文件中的字符串相当于一个密钥,一个节点要想加入某个集群,必须和所有节点的 .erlang.cookie 文件内容一致,所以通常将主节点的 .erlang.cookie 文件复制给其它节点。这里以 192.168.189.158 作为主节点,.erlang.cookie 文件位置需要在 RabbitMQ 启动日志中查看:
cat /var/log/rabbitmq/rabbit@centos158.log
2023-02-26 21:26:40.908761+08:00 [info] <0.222.0> Starting RabbitMQ 3.10.0 on Erlang 23.3.4.11 [emu]
2023-02-26 21:26:40.908761+08:00 [info] <0.222.0> Copyright (c) 2007-2022 VMware, Inc. or its affiliates.
2023-02-26 21:26:40.908761+08:00 [info] <0.222.0> Licensed under the MPL 2.0. Website: https://rabbitmq.com
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0>
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0> node : rabbit@centos158
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0> home dir : /var/lib/rabbitmq
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0> config file(s) : (none)
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0> cookie hash : 2cPR2mBWsaQ6fP0SWZ1QzA==
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0> log(s) : /var/log/rabbitmq/rabbit@centos158.log
2023-02-26 21:26:40.912755+08:00 [info] <0.222.0> : /var/log/rabbitmq/rabbit@centos158_upgrade.log
其中 home dir 即为 .erlang.cookie 文件位置,复制主节点服务器 .erlang.cookie 文件内容到其它两个节点,使三台服务器中的 .erlang.cookie 内容一致。
配置 hosts
配置三个服务器节点的 /etc/hosts 文件:添加节点名和节点IP的映射关系
192.168.189.156 centos156
192.168.189.157 centos157
192.168.189.158 centos158
重启网络 service network restart 测试是否能够互相 ping 通。
建立集群
注:在配置 .erlang.cookie 和 hosts 之前不要启动 RabbitMQ 节点。
建立集群之前首先启动主节点 192.168.189.158 (磁盘节点)
systemctl start rabbitmq-server.service
然后分别启动其余两个子节点 (内存节点) 并加入集群:
# 启动 RabbitMQ 服务
systemctl start rabbitmq-server.service
# 暂停应用以便加入集群
rabbitmqctl stop_app
# 清除全部数据(可选)
rabbitmqctl reset
# 作为内存节点加入集群
rabbitmqctl join_cluster --ram rabbit@centos158
# 恢复应用运行
rabbitmqctl start_app
查看集群状态
rabbitmqctl cluster_status
在任一节点的后台管理页面查看

配置镜像队列
在主节点执行如下命令:(添加一个节点,其它节点也都会有该策略)
# 设置集群所有节点及全部队列进行镜像
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
镜像队列详细配置可参考:
RabbitMQ集群配置镜像队列 - CSDN
https://blog.csdn.net/weixin_47026543/article/details/113563395
Classic Queue Mirroring — RabbitMQ
https://www.rabbitmq.com/ha.html
管理集群
# 退出集群
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
# 移除节点
# 关闭要移除的节点A
rabbitmqctl stop_app
# 在其他节点移除节点A
rabbitmqctl forget_cluster_node rabbit@rabbitName
负载均衡-HAProxy
安装HAProxy
在两个内存节点156和157分别安装 HAProxy
yum -y install haproxy
配置 HAProxy
cd /etc/haproxy/
cp haproxy.cfg haproxy.cfg.bak
配置文件内容全部覆盖
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
log 127.0.0.1 local2
chroot /var/lib/haproxy # 改变当前工作目录
pidfile /var/run/haproxy.pid # haproxy的pid存放路径,启动进程的用户必须有权限访问此文件
maxconn 4000 # 最大连接数,默认4000
user root # 指定haproxy运行时的用户身份
group root # 指定haproxy运行时的用户组
daemon # 创建1个进程进入deamon模式运行,此参数要求将运行模式设置为daemon
stats socket /var/lib/haproxy/stats # 创建监控所用的套接字目录
#---------------------------------------------------------------------
# defaults settings
#---------------------------------------------------------------------
# 注意:因为要使用tcp的负载,需要屏蔽掉与http相关的默认配置
defaults
mode http # 默认的模式mode { tcp|http|health },tcp是4层,http是7层,health只会返回OK
log global
# option httplog # 采用http日志格式
option dontlognull # 启用该项,日志中将不会记录空连接。所谓空连接就是在上游的负载均衡器
# option http-server-close # 每次请求完毕后主动关闭http通道
# option forwardfor except 127.0.0.0/8 # 如果后端服务器需要获得客户端真实ip需要配置的参数,可以从Http Header中获得客户端ip
option redispatch # serverId对应的服务器挂掉后,强制定向到其他健康的服务器
retries 3 # 3次连接失败就认为服务不可用,也可以通过后面设置
# timeout http-request 10s # http请求超时时间
timeout queue 1m # 队列超时时间
timeout connect 10s # 连接超时时间
timeout client 1m # 客户端连接超时时间
timeout server 1m # 服务器端连接超时时间
# timeout http-keep-alive 10s # 持久连接超时时间
timeout check 10s # 设置超时检查超时时间
maxconn 3000 # 最大连接数
###################### HAProxy统计页面配置 ######################################
listen status
bind 0.0.0.0:1080 # 监听端口
mode http # http的7层模式
stats enable
stats refresh 30s # 每隔?秒自动刷新监控页面
stats uri /haproxy/stats # 设置监控页面的url访问路径(http://localhost:1080/haproxy/stats)
stats auth admin:123456 # 设置监控页面的用户和密码(可配置多个用户)
stats realm (Haproxy\ statistic) # 监控页面的提示信息
stats hide-version # 隐藏监控页面版本信息
stats admin if TRUE # 手工启用/禁用后端服务器
###################### RabbitMQ集群web管理页面负载均衡配置 #######################
listen rabbitmq_admin
bind 0.0.0.0:15670 # 监听端口
balance roundrobin
server rmq156 192.168.189.156:15672
server rmq157 192.168.189.157:15672
####################### RabbitMQ集群负载均衡配置 #################################
listen rabbitmq_cluster
bind 0.0.0.0:5670
mode tcp# 负载均衡算法:支持 roundrobin,source,static-rr,leastconn,uri 等算法
balance roundrobin # 轮询算法# check inter 5000 是检测心跳频率
# rise 2是2次正确认为服务器可用
# fall 3是3次失败认为服务器不可用
server rmq156 192.168.189.156:5672 check inter 5000 rise 2 fall 3
server rmq157 192.168.189.157:5672 check inter 5000 rise 2 fall 3
启动 HAProxy
分别启动156和157的 HAProxy
# yum方式
systemctl start haproxy# 源码方式: 通过配置文件启动
haproxy -f /etc/haproxy/haproxy.cfg
启动报错
源码方式可正常启动,使用 systemctl 命令无法启动服务,查看服务状态日志如下:
一、报错信息为:cannot bind socket [0.0.0.0:xxxx]
root@centos156:/etc/haproxy # systemctl status haproxy
● haproxy.service - HAProxy Load BalancerLoaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled)Active: failed (Result: exit-code) since 一 2023-02-27 22:56:42 CST; 41s agoProcess: 14563 ExecStart=/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid $OPTIONS (code=exited, status=1/FAILURE)Main PID: 14563 (code=exited, status=1/FAILURE)2月 27 22:56:42 centos156 systemd[1]: Started HAProxy Load Balancer.
2月 27 22:56:42 centos156 haproxy-systemd-wrapper[14563]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
2月 27 22:56:42 centos156 haproxy-systemd-wrapper[14563]: [ALERT] 057/225642 (14566) : Starting proxy status: cannot bind socket [0.0.0.0:1080]
2月 27 22:56:42 centos156 haproxy-systemd-wrapper[14563]: [ALERT] 057/225642 (14566) : Starting proxy rabbitmq_admin: cannot bind socket [0.0.0.0:15670]
2月 27 22:56:42 centos156 haproxy-systemd-wrapper[14563]: [ALERT] 057/225642 (14566) : Starting proxy rabbitmq_cluster: cannot bind socket [0.0.0.0:5670]
2月 27 22:56:42 centos156 haproxy-systemd-wrapper[14563]: haproxy-systemd-wrapper: exit, haproxy RC=1
2月 27 22:56:42 centos156 systemd[1]: haproxy.service: main process exited, code=exited, status=1/FAILURE
2月 27 22:56:42 centos156 systemd[1]: Unit haproxy.service entered failed state.
2月 27 22:56:42 centos156 systemd[1]: haproxy.service failed.
1. 检查是否开启防火墙以及端口是否被占用
# 查看是否开启防火墙
systemctl status firewalld
# 查看端口是否被占用
netstat -tunlp | grep 1080
2. 查看 HAProxy 服务器中是否开启 Apache 或 Nginx 等 WEB 服务,如果有请先停掉这些服务。
2. 尝试关闭 selinux 或者 执行以下命令
setsebool -P haproxy_connect_any=1
3. HAProxy 配置了本机 IP 或 0.0.0.0 以外的 IP,比如虚拟 IP (Virtual IP)
1) # HAProxy 绑定非本机 IP 需要在 /etc/sysctl.conf 文件中进行配置:
# 修改内核参数
vim /etc/sysctl.conf
# 没有就新增此条记录
net.ipv4.ip_nonlocal_bind = 1
# 保存使结果生效
sysctl -p
2) # 确认是否开启内核转发功能
# 临时开启
echo 1 > /proc/sys/net/ipv4/ip_forward
# 永久生效
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
Haproxy启动故障:Starting proxy:cannot bind socke
https://blog.csdn.net/qq_31889553/article/details/102852256
HAProxy cannot bind socket [0.0.0.0:8888] - Stack Overflow
https://stackoverflow.com/questions/34793885/haproxy-cannot-bind-socket-0-0-0-08888
二、报错信息为: Cannot create pidfile /run/haproxy.pid
root@centos156:/etc/haproxy # systemctl status haproxy
● haproxy.service - HAProxy Load BalancerLoaded: loaded (/usr/lib/systemd/system/haproxy.service; disabled; vendor preset: disabled)Active: failed (Result: exit-code) since 一 2023-02-27 23:20:13 CST; 9s agoProcess: 16010 ExecStart=/usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid $OPTIONS (code=exited, status=1/FAILURE)Main PID: 16010 (code=exited, status=1/FAILURE)2月 27 23:20:13 centos156 systemd[1]: Started HAProxy Load Balancer.
2月 27 23:20:13 centos156 haproxy-systemd-wrapper[16010]: haproxy-systemd-wrapper: executing /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -p /run/haproxy.pid -Ds
2月 27 23:20:13 centos156 haproxy-systemd-wrapper[16010]: [ALERT] 057/232013 (16012) : [/usr/sbin/haproxy.main()] Cannot create pidfile /run/haproxy.pid
2月 27 23:20:13 centos156 haproxy-systemd-wrapper[16010]: haproxy-systemd-wrapper: exit, haproxy RC=1
2月 27 23:20:13 centos156 systemd[1]: haproxy.service: main process exited, code=exited, status=1/FAILURE
2月 27 23:20:13 centos156 systemd[1]: Unit haproxy.service entered failed state.
2月 27 23:20:13 centos156 systemd[1]: haproxy.service failed.
1. 检查 haproxy.cfg 配置的用户 user 是否拥有 root 权限
2. 尝试删除 /run/haproxy.pid 并重新启动 HAProxy 服务
测试 HAProxy
测试浏览器能正常访问以下两个地址的 RabbitMQ 管理页面
192.168.189.156:15670
192.168.189.157:15670
测试浏览器能正常访问以下两个地址的 HAProxy 监控页面 (amdin/123456)
192.168.189.156:1080/haproxy/stats
192.168.189.157:1080/haproxy/stats

主备-Keepalived
安装Keepalived
yum install -y keepalived
配置Keepalived
cd /etc/keepalived
cp keepalived.conf keepalived.conf.bak
156 作为主机 master 配置如下:
global_defs {router_id NodeA # 路由ID:主机与备机不能相同script_user rootenable_script_security
}vrrp_script chk_haproxy { # 自定义监控脚本script "/etc/keepalived/check_haproxy.sh"interval 5weight 2
}vrrp_instance VI_1 {state MASTER # 这里标记为主机Masterinterface ens33 # 这里的必须和你的网卡一致,ipconfig获得virtual_router_id 1 # 这里表示路由的唯一标识与备机一致priority 100 # 配置优先级:备机要小于主机advert_int 1 # 设置主备之间的检查时间,单位为sauthentication {auth_type PASS # 配置认证方式auth_pass root # 配置认证密码}virtual_ipaddress { # 配置虚拟ip地址,主备需保持一致,可设置多个192.168.189.159}track_script {chk_haproxy}
}
157 作为备机 backup 配置如下:
global_defs {router_id NodeB # 路由ID:主机与备机不能相同script_user rootenable_script_security
}vrrp_script chk_haproxy { # 自定义监控脚本script "/etc/keepalived/check_haproxy.sh"interval 5weight 2
}vrrp_instance VI_1 {state BACKUP # 这里标记为备机Backupinterface ens33 # 这里的必须和你的网卡一致,ipconfig获得virtual_router_id 1 # 这里表示路由的唯一标识与备机一致priority 50 # 配置优先级:备机要小于主机advert_int 1 # 设置主备之间的检查时间,单位为sauthentication {auth_type PASS # 配置认证方式auth_pass root # 配置认证密码}virtual_ipaddress { # 配置虚拟ip地址,主备需保持一致,可设置多个192.168.189.159}track_script {chk_haproxy}
}
编写监控脚本
vim /etc/keepalived/check_haproxy.sh
#!/bin/bash
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ];then
service haproxy start
fi
sleep 2
if [ $(ps -C haproxy --no-header | wc -l) -eq 0 ];then
service keepalived stop
fi
# 添加可执行权限
chmod 755 /etc/keepalived/check_haproxy.sh
check_haproxy.sh 脚本作用
如果 HAProxy 服务挂了,尝试重启;如果重启不成功,则关闭 Keepalived 服务,自动切换到 backup。
启动 Keepalived
先启动 156 master 再启动 157 backup
service keepalived start
监测 Keepalived
1. 查看 Keepalived 状态
service keepalived status
2. 查看 Keepalived 日志输出
tail -200f /var/log/messages
3. 查看添加的虚拟IP (master)
ip add show
4. master 模拟异常关闭
service keepalived stop
master 关闭后对应的虚拟IP也会消失,backup 成为新的 master,异常 master 重启后会重新恢复为 master 。
5. master 模拟 HAProxy 异常关闭
service haproxy stop
测试 HAProxy 异常关闭后,打印 Keepalived 日志查看监控脚本是否正常执行。
# 打印 Keepalived 日志
tail -200f /var/log/messages
# 正常启动脚本日志信息(注意succeeded)
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: VRRP_Instance(VI_1) Entering MASTER STATE
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: VRRP_Instance(VI_1) setting protocol VIPs.
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.189.159
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:05 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:05 centos156 avahi-daemon[816]: Registering new address record for 192.168.189.159 on ens33.IPv4.
Feb 28 03:42:06 centos156 Keepalived_vrrp[37334]: VRRP_Script(chk_haproxy) succeeded
Feb 28 03:42:07 centos156 Keepalived_vrrp[37334]: VRRP_Instance(VI_1) Changing effective priority from 100 to 102
Feb 28 03:42:10 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:10 centos156 Keepalived_vrrp[37334]: VRRP_Instance(VI_1) Sending/queueing gratuitous ARPs on ens33 for 192.168.189.159
Feb 28 03:42:10 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:10 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:10 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
Feb 28 03:42:10 centos156 Keepalived_vrrp[37334]: Sending gratuitous ARP on ens33 for 192.168.189.159
解决 Keepalived 监测脚本一直不执行
https://blog.csdn.net/Bb15070047748/article/details/106276491
解决Keepalived脚本启动时warning、unsafe、not executable - CSDN
https://blog.csdn.net/Kangyucheng/article/details/110122893
测试虚拟 IP
浏览器通过虚拟IP访问能正常打开 RabbitMQ 管理页面 和 HAProxy 监控页面


应用访问集群
1. IP 为 Keepalived 中配置的虚拟IP
2. PORT 为 RabbitMQ 默认的 5672
3. 账号密码同 RabbitMQ
参考资料
单机RabbitMQ集群的搭建及高可用集群原理分析 - 知乎 (zhihu.com)
https://zhuanlan.zhihu.com/p/350446326
高可用RabbitMQ集群的搭建和使用 - 劈天造陆 - 博客园 (cnblogs.com)
https://www.cnblogs.com/java-spring/p/8855862.html
HAProxy安装与配置 - 我爱吃芹菜~ - 博客园 (cnblogs.com)
https://www.cnblogs.com/leixixi/p/14749322.html
rabbitmq搭建集群踩坑记 - 腾讯云开发者社区-腾讯云 (tencent.com)
https://cloud.tencent.com/developer/article/1683781
相关文章:
基于 HAProxy + Keepalived 搭建 RabbitMQ 高可用集群
RabbitMQ 集群 通常情况下,在集群中我们把每一个服务称之为一个节点,在 RabbitMQ 集群中,节点类型可以分为两种: 内存节点:元数据存放于内存中。为了重启后能同步数据,内存节点会将磁盘节点的地址存放于磁…...
基于51单片机和proteus的智能调速风扇设计
此智能风扇是基于51单片机和proteus的仿真设计,功能如下: 1. Timer0 PWM控制电机转速 2. DHT11采集温湿度 3. LCD1602显示温湿度及电机状态 4. 按键控制电机加减速启停等 5. 串口控制电机加减速启停等 功能框图如下: Proteus仿真界面如下…...
SQL Server开启CDC的完整操作过程
这里写自定义目录标题写在前面SQL Server开启CDC1. 将指定库的实例先开启CDC2. 开启需要开启CDC的表3. 关闭CDC功能更详细信息参照官网写在前面 鉴于老旧数据的结构和项目都在sqlserver上存储,且迁移成本巨大,当下要为sqlserver的存储过程减负。要将一部…...
【Spring Cloud Alibaba】008-Sentinel
【Spring Cloud Alibaba】008-Sentinel 文章目录【Spring Cloud Alibaba】008-Sentinel一、服务雪崩1、概述2、解决方案常见的容错机制二、Sentinel:分布式系统的流量防卫兵1、**Sentinel** 概述简介特性Sentinel 的开源生态Sentinel 的历史2、Sentinel 基本概念资源…...
解读CRC校验计算
个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 参考:http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html 参考:https://en.wikipedia.org/wiki/Cyclic_redundancy_check 参考:https://www.cnblogs.com/…...
深入理解Spring MVC下
上一篇博客从理论概念上来梳理Spring MVC相关知识,此篇博客将通过spring官网提供showcase代码为例子,详细介绍showcase代码中包含的各个例子是如何实现的。官网的showcase代码包含的主要例子包括,Demo地址:Mapping Requests&#…...
【Linux】ssh-keygen不需要回车,自动生成密钥,批量免密操作!
使用命令ssh-keygen 需要手动敲击回车,才会生成密钥,如下代码所示 [rootlocalhost ~]# ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase):…...
C/C++开发,无可避免的内存管理(篇四)-智能指针备选
一、智能指针 采用C/C开发堆内存管理无论是底层开发还是上层应用,无论是开发新手,还是多年的老手,都会不自觉中招,尤其是那些不是自己一手经历的代码,要追溯问题出在哪里更是个麻烦事。C/C程序常常会遇到程序突然退出&…...
VMware ESXi给虚拟机扩容
用ESXi管理的虚拟机硬盘空间不够了,讲一下如何进行扩容。 一、查看现状 通过如下三个命令,可以查看硬盘情况,可以看到只有500G,已经用了45%。这次我们再扩容500G。 df -Th lsblk fdisk -lIDE磁盘的文件名为 /de…...
认识STM32和如何构建STM32工程
STM32介绍什么是单片机单片机(Single-Chip Microcomputer)是一种集成电路芯片,把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种/0口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电…...
RabbitMQ延迟队列
目录 一、概念 二、使用场景 三、RabbitMQ 中的 TTL (一)队列设置 TTL (二)消息设置 TTL (三)两者的区别 四、整合SpringBoot实现延迟队列 (一)创建项目 (二&am…...
Java中常用的七种队列你了解多少?
文章目录Java中常用的七种队列你了解多少?ArrayBlockingQueue队列如何使用?添加元素到队列获取队列中的元素遍历队列LinkedBlockingQueue队列如何使用?1. 创建SynchronousQueue对象2. 添加元素到队列3. 获取队列中的元素4. 遍历队列SynchronousQueue队列…...
<Java获取时间日期工具类>常见八种场景(一)
一:自定义时间日期工具类常用的八种方式(整理): 0,getTimeSecondNum:时间日期转成秒数,常用于大小比较 1,getLastYearMonthLastDay:获取去年当月最后一天的时间日期 2,getLastYearM…...
接上一篇 对多个模型环形旋转进行优化 指定旋转位置
using System.Collections; using System.Collections.Generic; using UnityEngine; using DG.Tweening; public class ModelAnimal : MonoBehaviour { //记录鼠标滑动 public Vector2 lastPos;//鼠标上次位置 Vector2 currPos;//鼠标当前位置 Vector2 offset;//两次位置的偏移…...
Unity中获取地形的法线
序之前,生成了地形图:(42条消息) 从灰度图到地形图_averagePerson的博客-CSDN博客那末,地形的法线贴图怎么获取?大概分为两个部分吧,先拿到法线数据,再画到纹理中去。关于法线计算Unity - Scripting API: M…...
模型解释性:PFI、PDP、ICE等包的用法
本篇主要介绍几种其他较常用的模型解释性方法。 1. Permutation Feature Importance(PFI) 1.1 算法原理 置换特征重要性(Permutation Feature Importance)的概念很简单,其衡量特征重要性的方法如下:计算特征改变后模型预测误差的增加。如果打乱该特征的…...
spring常见面试题(2023最新)
目录前言1.spring是什么2.spring的设计核心是什么3.IOC和AOP面试题4.spring的优点和缺点5.spring中bean的作用域6.spring中bean的注入方式7.BeanFactory 和 ApplicationContext有什么区别?8.循环依赖的情况,怎么解决?9.spring中单例Bean是线程…...
华为OD机试题,用 Java 解【压缩报文还原】问题
最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...
机器学习-BM-FKNCN、BM-FKNN等分类器对比实验
目录 一、简介和环境准备 二、算法简介 2.1四种方法类: 2.1.1FKNN 2.1.2FKNCN 2.1.3BM-FKNN 2.1.3BM-FKNCN 2.2数据预处理 2.3输出视图 2.4调用各种方法看准确率 2.4.1BM-FKNCN 2.4.2BM-FKNN 2.4.3FKNCN 2.4.4FKNN 2.4.5KNN 一、简介和环境准备 k…...
ChatGPT火了,对话式人工智能还能干嘛?
身兼数职的ChatGPT 从2022火到了2023 连日来一直是各大平台的热议对象 其实除了写诗、敲代码、处理文档 以ChatGPT为代表的 对话式人工智能 还有更重要的工作要做 对话式AI与聊天机器人 相信大多数人…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
leetcodeSQL解题:3564. 季节性销售分析
leetcodeSQL解题:3564. 季节性销售分析 题目: 表:sales ---------------------- | Column Name | Type | ---------------------- | sale_id | int | | product_id | int | | sale_date | date | | quantity | int | | price | decimal | -…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
3-11单元格区域边界定位(End属性)学习笔记
返回一个Range 对象,只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意:它移动的位置必须是相连的有内容的单元格…...
从物理机到云原生:全面解析计算虚拟化技术的演进与应用
前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...
