当前位置: 首页 > news >正文

基于 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 是一个开源的、高性能的负载均衡软件,同样可以作为负载均衡软件的还有 nginxlvs 等。 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集群配置镜像队列 - CSDNhttps://blog.csdn.net/weixin_47026543/article/details/113563395

Classic Queue Mirroring — RabbitMQhttps://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 sockehttps://blog.csdn.net/qq_31889553/article/details/102852256

HAProxy cannot bind socket [0.0.0.0:8888] - Stack Overflowhttps://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 - CSDNhttps://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 集群 通常情况下&#xff0c;在集群中我们把每一个服务称之为一个节点&#xff0c;在 RabbitMQ 集群中&#xff0c;节点类型可以分为两种&#xff1a; 内存节点&#xff1a;元数据存放于内存中。为了重启后能同步数据&#xff0c;内存节点会将磁盘节点的地址存放于磁…...

基于51单片机和proteus的智能调速风扇设计

此智能风扇是基于51单片机和proteus的仿真设计&#xff0c;功能如下&#xff1a; 1. Timer0 PWM控制电机转速 2. DHT11采集温湿度 3. LCD1602显示温湿度及电机状态 4. 按键控制电机加减速启停等 5. 串口控制电机加减速启停等 功能框图如下&#xff1a; Proteus仿真界面如下…...

SQL Server开启CDC的完整操作过程

这里写自定义目录标题写在前面SQL Server开启CDC1. 将指定库的实例先开启CDC2. 开启需要开启CDC的表3. 关闭CDC功能更详细信息参照官网写在前面 鉴于老旧数据的结构和项目都在sqlserver上存储&#xff0c;且迁移成本巨大&#xff0c;当下要为sqlserver的存储过程减负。要将一部…...

【Spring Cloud Alibaba】008-Sentinel

【Spring Cloud Alibaba】008-Sentinel 文章目录【Spring Cloud Alibaba】008-Sentinel一、服务雪崩1、概述2、解决方案常见的容错机制二、Sentinel&#xff1a;分布式系统的流量防卫兵1、**Sentinel** 概述简介特性Sentinel 的开源生态Sentinel 的历史2、Sentinel 基本概念资源…...

解读CRC校验计算

个人随笔 (Owed by: 春夜喜雨 http://blog.csdn.net/chunyexiyu) 参考&#xff1a;http://www.sunshine2k.de/articles/coding/crc/understanding_crc.html 参考&#xff1a;https://en.wikipedia.org/wiki/Cyclic_redundancy_check 参考&#xff1a;https://www.cnblogs.com/…...

深入理解Spring MVC下

上一篇博客从理论概念上来梳理Spring MVC相关知识&#xff0c;此篇博客将通过spring官网提供showcase代码为例子&#xff0c;详细介绍showcase代码中包含的各个例子是如何实现的。官网的showcase代码包含的主要例子包括&#xff0c;Demo地址&#xff1a;Mapping Requests&#…...

【Linux】ssh-keygen不需要回车,自动生成密钥,批量免密操作!

使用命令ssh-keygen 需要手动敲击回车&#xff0c;才会生成密钥&#xff0c;如下代码所示 [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开发堆内存管理无论是底层开发还是上层应用&#xff0c;无论是开发新手&#xff0c;还是多年的老手&#xff0c;都会不自觉中招&#xff0c;尤其是那些不是自己一手经历的代码&#xff0c;要追溯问题出在哪里更是个麻烦事。C/C程序常常会遇到程序突然退出&…...

VMware ESXi给虚拟机扩容

用ESXi管理的虚拟机硬盘空间不够了&#xff0c;讲一下如何进行扩容。 一、查看现状 通过如下三个命令&#xff0c;可以查看硬盘情况&#xff0c;可以看到只有500G&#xff0c;已经用了45%。这次我们再扩容500G。 df -Th lsblk fdisk -lIDE磁盘的文件名为        /de…...

认识STM32和如何构建STM32工程

STM32介绍什么是单片机单片机(Single-Chip Microcomputer)是一种集成电路芯片&#xff0c;把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种/0口和中断系统、定时器/计数器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电…...

RabbitMQ延迟队列

目录 一、概念 二、使用场景 三、RabbitMQ 中的 TTL &#xff08;一&#xff09;队列设置 TTL &#xff08;二&#xff09;消息设置 TTL &#xff08;三&#xff09;两者的区别 四、整合SpringBoot实现延迟队列 &#xff08;一&#xff09;创建项目 &#xff08;二&am…...

Java中常用的七种队列你了解多少?

文章目录Java中常用的七种队列你了解多少?ArrayBlockingQueue队列如何使用&#xff1f;添加元素到队列获取队列中的元素遍历队列LinkedBlockingQueue队列如何使用&#xff1f;1. 创建SynchronousQueue对象2. 添加元素到队列3. 获取队列中的元素4. 遍历队列SynchronousQueue队列…...

<Java获取时间日期工具类>常见八种场景(一)

一:自定义时间日期工具类常用的八种方式&#xff08;整理&#xff09;: 0&#xff0c;getTimeSecondNum&#xff1a;时间日期转成秒数&#xff0c;常用于大小比较 1&#xff0c;getLastYearMonthLastDay&#xff1a;获取去年当月最后一天的时间日期 2&#xff0c;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中获取地形的法线

序之前&#xff0c;生成了地形图&#xff1a;(42条消息) 从灰度图到地形图_averagePerson的博客-CSDN博客那末&#xff0c;地形的法线贴图怎么获取&#xff1f;大概分为两个部分吧&#xff0c;先拿到法线数据&#xff0c;再画到纹理中去。关于法线计算Unity - Scripting API: M…...

模型解释性:PFI、PDP、ICE等包的用法

本篇主要介绍几种其他较常用的模型解释性方法。 1. Permutation Feature Importance(PFI) 1.1 算法原理 置换特征重要性(Permutation Feature Importance)的概念很简单&#xff0c;其衡量特征重要性的方法如下&#xff1a;计算特征改变后模型预测误差的增加。如果打乱该特征的…...

spring常见面试题(2023最新)

目录前言1.spring是什么2.spring的设计核心是什么3.IOC和AOP面试题4.spring的优点和缺点5.spring中bean的作用域6.spring中bean的注入方式7.BeanFactory 和 ApplicationContext有什么区别&#xff1f;8.循环依赖的情况&#xff0c;怎么解决&#xff1f;9.spring中单例Bean是线程…...

华为OD机试题,用 Java 解【压缩报文还原】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

机器学习-BM-FKNCN、BM-FKNN等分类器对比实验

目录 一、简介和环境准备 二、算法简介 2.1四种方法类&#xff1a; 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与聊天机器人      相信大多数人…...

十一、操作数栈的特点(Operand Sstack)

1.每一个独立的栈帧中除了包含局部变量表以外&#xff0c;还包含一个后进先出的操作数栈&#xff0c;也可以称之为表达式栈。 2.操作数栈&#xff0c;在方法执行过程中&#xff0c;根据字节码指令&#xff0c;往栈中写入数据&#xff0c;或提取数据&#xff0c;即入栈&#xff…...

拆解瑞幸新用户激活流程,如何让用户“动”起来?

Aha时刻 一个产品的拉新环节,是多种方式并存的;新用户可能来自于商务搭建了新的渠道,运营策划了新的活动,企划发布了新的广告,销售谈下了新的客户,市场推广了新的群体,以及产品本身的口碑传播,功能更新带来的自然流量。 这是一个群策群力的环节,不同的团队背负不同的K…...

tkinter界面的TCP通信/开启线程等待接收数据

前言 用简洁的语言写一个可以与TCP客户端实时通信的界面。之前做了一个项目是要与PLC进行信息交互的界面&#xff0c;在测试的时候就利用TCP客户端来实验&#xff0c;文末会附上TCP客户端。本文分为三部分&#xff0c;第一部分是在界面向TCP发送数据&#xff0c;第二部分是接收…...

华为OD机试题,用 Java 解【任务混部】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…...

看linux内核启动流程需要的汇编指令解释

一、指令 0.MRS 和MSR MRS 指令: 对状态寄存器CPSR和SPSR进行读操作。 MSR指令: 对状态寄存器CPSR和SPSR进行写操作。 1.adrp adrp x0, boot_args把boot_args的页基地址提取出来&#xff0c;放到x0中。 2.stp stp x21, x1, [x0]将 x21, x1 的值存入 x0寄存器记录的地址中…...

【巨人的肩膀】JAVA面试总结(二)

1、&#x1f4aa; 目录1、&#x1f4aa;1.0、什么是面向对象1.1、JDK、JRE、JVM之间的区别1.2、什么是字节码1.3、hashCode()与equals()之间的联系1.4、String、StringBuffer、StringBuilder的区别1.5、和equals方法的区别1.6、重载和重写的区别1.7、List和Set的区别1.8、Array…...

【网络安全入门】零基础小白必看!!!

看到很多小伙伴都想学习 网络安全 &#xff0c;让自己掌握更多的 技能&#xff0c;但是学习兴趣有了&#xff0c;却发现自己不知道哪里有 学习资源◇瞬间兴致全无&#xff01;◇ &#x1f604;在线找人要资料太卑微&#xff0c;自己上网下载又发现要收费0 &#x1f643;差点当…...

字节前端经典面试题(附答案)

有哪些可能引起前端安全的问题? 跨站脚本 (Cross-Site Scripting, XSS): ⼀种代码注⼊⽅式, 为了与 CSS 区分所以被称作 XSS。早期常⻅于⽹络论坛, 起因是⽹站没有对⽤户的输⼊进⾏严格的限制, 使得攻击者可以将脚本上传到帖⼦让其他⼈浏览到有恶意脚本的⻚⾯, 其注⼊⽅式很简…...

数据库管理工具的使用

目录 摘要 一、Navicat是什么&#xff1f; 二、使用步骤 1.如何下载与安装 2.如何连接远程数据库 总结 摘要 本文主要介绍数据库管理工具的使用 一、Navicat是什么&#xff1f; 它是一款数据库管理工具&#xff0c;将此工具连接数据库,你可以从中看到各种数据库的详细…...

让马斯克反悔的毫米波雷达,被国产雷达头部厂商木牛科技迭代到了5D时代

近日&#xff0c;特斯拉或将在其HW4.0硬件系统配置一枚高精度4D毫米波雷达的消息在外网刷屏。据分析&#xff0c;“纯视觉”信仰者马斯克之所以做出这样的决定&#xff0c;一方面是减配了雷达的特斯拉自动驾驶&#xff0c;表现不尽如人意&#xff1b;另一方面也跟毫米波雷达的技…...

点击图片进入网站怎么做/seo关键词选取工具

前言随着自己开发的应用的版本迭代&#xff0c;新功能不断增多&#xff0c;随之引入的第三方库也不可避免地多了起来&#xff0c;你可能就会发现自己应用Application中各种框架的初始化代码也在逐渐臃肿起来&#xff1a;什么推送啦&#xff0c;分享啦&#xff0c;统计啦&#x…...

成都网站建设门户/线上平台推广方式

解决jQuery和其他库的冲突 当把jQuery和其他JavaScript库&#xff08;例如Prototype、MooTools或YUI&#xff09;一起使用时 <script> jQuery.noConflict();//将变量$的控制权让渡给prototype.js jQuery(function ($) {//使用jQuery设定页面加载时执行的函数 $("p&q…...

昆山自适应网站建设/百度下载安装2019

自学是一件很有趣的事&#xff0c;一旦和某种有目的性的行为挂钩&#xff0c;估计趣味就会降低很多。自从开始学习java的时候&#xff0c;就决定一如既往的走下去&#xff0c;不离不弃。 虽然&#xff0c;Sun已经离开了很久&#xff0c;但是java爱好者开发者依然激情饱满&#…...

有个专门做装修的网站/品牌营销是什么

PHP导出excel想必很多童鞋都碰到了&#xff0c;使用phpexcel类也确实方便&#xff0c;但导出大量数据的时候就没那么简单了&#xff0c;常常会伴随一些超时或内存溢出的问题&#xff0c;下面就给大家介绍一些方法&#xff0c;文章由原作者整理&#xff0c;出处PHPExcel导出大量…...

广东宇晟建设工程有限公司网站/十大互联网广告公司

在日常开发中我们经常会碰到小数计算&#xff0c;而小数直接计算的话会出现一些小小的错误&#xff0c;如下 System.out.println(1.01 2.02); 复制代码你说能输出什么&#xff1f;3.03&#xff1f;实际上输出的是3.0300000000000002。这是因为不论是float 还是double都是浮点…...

鹤山市网站建设公司/长春百度推广公司

一个ListView显示出来需要3个东西&#xff1a; 1&#xff0c;listview&#xff08;用来显示数据的列表&#xff09;。 2&#xff0c;Data(需要显示的数据)。 3&#xff0c;一个绑定Data和Listview的适配器ListAdapter。 一&#xff0c;ListView 1&#xff0c;ListView的每一项其…...