概述
1:环境准备
使用 hostnamectl 在三台机器上修改主机名 分别为 basic basic02 basic03
vi /etc/hosts 在三台机器上分别添加如下内容
192.168.217.128 basic
192.168.217.136 basic02
192.168.217.135 basic03
在生产环境需要开端口
4369 Erlang端口
25672 集群通信端口
15672 Rabbitmq管理控制台端口
5672 Rabbitmq服务端口
8100 HAProxy 配置监控页面绑定端口
5671 HAProxy rabbitmq_cluster集群通信端口
学习的时候只需要关闭防火墙
同时还需要关闭 selinux ,关闭selinux如果不关闭,会阻止其他的应用执行shell脚本
SELINUX=enforcing
#此项定义selinux状态。
#enforcing—是强制模式系统受selinux保护,违反了策略将无法继续操作
#permissive—是提示模式系统不会受到selinux保护,只是收到警告信息
permissive就是Selinux有效,但是即使你违反了策略任然可以继续操作
但是会把违反安全的内容记录下来(警告信息)
#disabled—禁用selinux
SELINUXTYPE=targeted
#此项定义selinux使用哪个策略模块保护系统。targeted只对apache,sendmail,bind,postgresql,nfs,cifs等网络服务保护。
以上策略配置都放置在/etc/selinux目录中,目录和策略名称相同
getenforce 查看 selinux 状态
setenforce 临时禁用 sudo setenforce 0 状态变为 Permissive
永久关闭SELINUX
修改方式1: vim /etc/selinux/config
修改 SELINUX=enforcing 为 SELINUX=disabled
reboot
修改方式2:
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
grep SELINUX=disabled /etc/selinux/config
reboot
修改完成之后 查看状态
getenforce
2:Rabbitmq 安装
在三台机器都安装 Erlang 环境,因为 RabbitMQ 运行需要Erlang支持
安装步骤请参考 RabbitMQ 实战_Java 码农的博客-CSDN博客
3: 集群安装
当单台 RabbitMQ 服务器的处理消息的能力达到瓶颈时,此时可以通过 RabbitMQ 集群来进行扩展,从而达到提升吞吐量的目的。集群还有可以解决单点问题当节点挂掉以后,集群中的其他节点可以继续提供服务,当出现问题的几点修复后小虹心加入集群可以继续提供服务,节点间信息是相互同步的, RabbitMQ 集群是一个或多个节点的逻辑分组,集群中的每个节点都是对等的,每个节点共享所有的用户,虚拟主机,队列,交换器,绑定关系,运行时参数和其他分布式状态等信息.
3.1: 普通集群
在完成三台机器上的 Erlang 和 RabbitMq之后 ,将basic上的 .erlang.cookie文件拷贝到其他两台主机上(basic02,basic03) ,cookie文件相当于密钥令牌,集群中的RabbitMQ节点需要通过交换密钥令牌以获得相互认证,否则在搭建过程中会出现 Authentication Fail错误。RabbitMQ服务启动时,erlangVM会自动创建该cookie文件.
启动 rabbitmq 的时候 报错
rabbitmq-server -detached 会同时启动 Erlang 和 Rabbitmq
rabbitmqctl start_app 开启 rabbitmqctl start_app 关闭 (这两个只启动或关闭 Rabbitmq)
查看.erlang.cookie文件目录 默认的存储路径为 /var/lib/rabbitmq/.erlang.cookie
ls -la /var/lib/rabbitmq/
cat .erlang.cookie
查看 .erlang.cookie 的内容
关闭三个机器上的服务 rabbitmqctl stop
在basic 执行拷贝命令将.erlang.cookie 拷贝到basic02,basic03的/var/lib/rabbitmq/目录下
scp /var/lib/rabbitmq/.erlang.cookie root@basic02:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@basic03:/var/lib/rabbitmq/
cookie文件原来的权限改为 400
再次查看.erlang.cookie 的内容,cookie 一致了
cat /root/.erlang.cookie
在三台主机上均执行以下命令,启动 RabbitMQ 服务
rabbitmqctl start_app
启动的时候可以看到三台机器的 hash 都是相同的了,说明 .erlang.cookie 一致并且生效了
rabbitmq-server -detached 命令会同时启动 Erlang 虚拟机和 RabbitMQ 应用服务而
rabbitmqctl start_app
只会启动 RabbitMQ 应用服务, rabbitmqctl stop_app
只会停止 RabbitMQ 服务
RabbitMQ 集群的搭建需要选择其中任意一个节点为基准
将其它节点逐步加入,这里我们以basic为基准节点将basic02 和 basic03 加入集群
在basic02 和 basic03 上执行以下命令:
basic02 上执行
# .启动服务
rabbitmqctl start_app
在basic03 上执行以下命令:
# .停止服务
rabbitmqctl stop_app
# .重置状态
rabbitmqctl reset
# .节点加入
rabbitmqctl join_cluster --disc rabbit@basic
# .启动服务
rabbitmqctl start_app
basic03 上执行
# .启动服务
rabbitmqctl start_app
在basic03 上执行以下命令:
# .停止服务
rabbitmqctl stop_app
# .重置状态
rabbitmqctl reset
# .节点加入
rabbitmqctl join_cluster --ram rabbit@basic02
# .启动服务
rabbitmqctl start_app
不要把两个节点都 往 basic 上挂 否者会报异常
Starting node rabbit@basic03 ...
Error:
{:rabbit, {{:timeout_waiting_for_tables, [:rabbit@basic02, :rabbit@basic, :rabbit@basic03], [:rabbit_delayed_messagerabbit@basic03, :rabbit_delayed_messagerabbit@basic03_index]}, {:rabbit, :start, [:normal, []]}}}
如果出现了这个异常 需要做如下步骤 (重要)
rabbitmqctl stop_app
rm -rf /var/lib/rabbitmq/mnesia/*
rabbitmqctl forget_cluster_node rabbit@basic03
在发生错误的节点执行
rabbitmqctl stop_app
删除 rm -rf /var/lib/rabbitmq/mnesia/* 删除 文件
主节点中将该节点移除集群: rabbitmqctl forget_cluster_node rabbit@发生错误的主机名basic03
然后 重启该节点
rabbitmqctl start_app
再此执行
# .停止服务
rabbitmqctl stop_app
# .重置状态
rabbitmqctl reset
# .节点加入
rabbitmqctl join_cluster --ram rabbit@basic02 把Basic03加入到Basic02 ,而不是 Basic
# .启动服务
rabbitmqctl start_app
此时一个普通集群就搭建起来了,我们可以查看管理控制台,
其他节点:
rabbitmqctl cluster_status 在任意一个节点查看集群状态
但是默认的这种集群,是无法在各个节点之间保存数据的,数据只会保存在接受到消息的节点上
当 ram 的节点挂了之后 数据会丢失
3.2: 镜像集群
开启镜像集群,这里我们为所有队列开启镜像配置,高可用策略,其语法如下:
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' 表示开启HA模式 适用于所有的队列
在上面我们指定了 ha-mode 的值为 all ,代表消息会被同步到所有节点的相同队列中。这里我们之所以这样配置,因为我们本身只有三个节点,因此复制操作的性能开销比较小。如果你的集群有很多节点,那么此时复制的性能开销就比较大,此时需要选择合适的复制系数。通常可以遵循过半写原则,即对于一个节点数为 n 的集群,只需要同步到 n/2+1 个节点上即可。此时需要同时修改镜像策略为 exactly,并指定复制系数 ha-params,示例命令如下:
给默认的 所有的 添加高可用策略
rabbitmqctl set_policy ha-two "^" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
给指定的 /MSA 添加高可用策略
rabbitmqctl set_policy ha-two "/MSA" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
官网的 镜像高可用配置
Classic Queue Mirroring — RabbitMQ
其他策略配置
官网路径 Parameters and Policies — RabbitMQ
除此之外,RabbitMQ 还支持使用正则表达式来过滤需要进行镜像操作的队列,示例如下:
rabbitmqctl set_policy ha-all "^ha." '{"ha-mode":"all"}'
节点下线
以上介绍的集群搭建的过程就是服务扩容的过程,如果想要进行服务缩容,即想要把某个节点剔除集群,有两种可选方式:
第一种:可以先使用 rabbitmqctl stop 停止该节点上的服务,然后在其他任意一个节点上执行 forget_cluster_node 命令。
这里以剔除 basic03 上的服务为例,此时可以在 basic01 或 basic02 上执行下面的命令:
rabbitmqctl forget_cluster_node rabbit@basic03
第二种方式:先使用 rabbitmqctl stop
停止该节点上的服务,然后再执行 rabbitmqctl reset
这会清空该节点上所有历史数据,并主动通知集群中其它节点它将要离开集群。
没有一个直接的命令可以关闭整个集群,需要逐一进行关闭。但是需要保证在重启时,最后关闭的节点最先被启动。如果第一个启动的不是最后关闭的节点,那么这个节点会等待最后关闭的那个节点启动,默认进行 10 次连接尝试,超时时间为 30 秒,如果依然没有等到,则该节点启动失败
使用镜像集群的代码 后面还会贴上来:
依赖:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <!-- 必须的依赖 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2.RELEASE</version> <relativePath/> </parent> <groupId>org.rsp</groupId> <artifactId>rabbitMQ-sp</artifactId> <version>1.0-SNAPSHOT</version> <name>rabbitMQ-sp</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> <!-- 必须的依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-amqp</artifactId> </dependency> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.amqp/spring-rabbit-test --> <dependency> <groupId>org.springframework.amqp</groupId> <artifactId>spring-rabbit-test</artifactId> <version>2.3.10</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.22</version> <scope>provided</scope> </dependency> <!--swagger图形化接口 開始--> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.9.2</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.9.2</version> </dependency> <!--swagger图形化接口結束--> <!-- https://mvnrepository.com/artifact/commons-io/commons-io --> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.9.0</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
配置类
package org.rsp.config; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.Binding; import org.springframework.amqp.core.BindingBuilder; import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.core.Queue; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; /** Broker:它提供一种传输服务,它的角色就是维护一条从生产者到消费者的路线,保证数据能按照指定的方式进行传输, Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。 Queue:消息的载体,每个消息都会被投到一个或多个队列。 Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来. Routing Key:路由关键字,exchange根据这个关键字进行消息投递。 vhost:虚拟主机,一个broker里可以有多个vhost,用作不同用户的权限分离。 Producer:消息生产者,就是投递消息的程序. Consumer:消息消费者,就是接受消息的程序. Channel:消息通道,在客户端的每个连接里,可建立多个channel. */ @Slf4j @Configuration public class RabbitConfig2 { @Value("${spring.rabbitmq.addresses}") private String addresses; @Value("${spring.rabbitmq.username}") private String username; @Value("${spring.rabbitmq.password}") private String password; public static final String EXCHANGE_A = "my-mq-exchange_A"; public static final String EXCHANGE_B = "my-mq-exchange_B"; public static final String EXCHANGE_C = "my-mq-exchange_C"; public static final String QUEUE_A = "QUEUE_A"; public static final String QUEUE_B = "QUEUE_B"; public static final String QUEUE_C = "QUEUE_C"; public static final String ROUTINGKEY_A = "spring-boot-routingKey_A"; public static final String ROUTINGKEY_B = "spring-boot-routingKey_B"; public static final String ROUTINGKEY_C = "spring-boot-routingKey_C"; //使用自定义工厂类的方式 ,这种方式适合于 要区别 不同的 vitural host 的时候 //需要将工厂类和模板类区根据业务别开的时候使用 @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setAddresses(addresses); connectionFactory.setUsername(username); connectionFactory.setPassword(password); connectionFactory.setVirtualHost("/MSA"); connectionFactory.setPublisherConfirms(true); //开启发布确认 return connectionFactory; } @Bean @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) //必须是prototype类型 public RabbitTemplate rabbitTemplate() { RabbitTemplate template = new RabbitTemplate(connectionFactory()); return template; } //定义交换机 队列 路由 和绑定关系 /** * 针对消费者配置 * 1. 设置交换机类型 * 2. 将队列绑定到交换机 FanoutExchange: 将消息分发到所有的绑定队列,无routingkey的概念 HeadersExchange :通过添加属性key-value匹配 DirectExchange:按照routingkey分发到指定队列 TopicExchange:多关键字匹配 */ @Bean public DirectExchange defaultExchange() { return new DirectExchange(EXCHANGE_A); } /** * 获取队列A * @return */ @Bean public Queue queueA() { return new Queue(QUEUE_A, true); //队列持久 } @Bean public Binding binding() { return BindingBuilder.bind(queueA()).to(defaultExchange()).with(RabbitConfig2.ROUTINGKEY_A); } }
配置文件:
spring: rabbitmq: addresses: 192.168.217.128:5672,192.168.217.135:5672,192.168.217.136:5672 username: developer password: dev123456 virtual-host: /MSA server: port: 8888
生产者:
package org.rsp.producer; import lombok.extern.slf4j.Slf4j; import org.rsp.config.RabbitConfig2; import org.springframework.amqp.rabbit.connection.CorrelationData; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.UUID; @Slf4j @Component public class MsgProducer implements RabbitTemplate.ConfirmCallback { //由于rabbitTemplate的scope属性设置为ConfigurableBeanFactory.SCOPE_PROTOTYPE,所以不能自动注入 private RabbitTemplate rabbitTemplate; /** * 构造方法注入rabbitTemplate */ @Autowired public MsgProducer(RabbitTemplate rabbitTemplate) { this.rabbitTemplate = rabbitTemplate; rabbitTemplate.setConfirmCallback(this); //rabbitTemplate如果为单例的话,那回调就是最后设置的内容 } public void sendMsg(String content) { CorrelationData correlationId = new CorrelationData(UUID.randomUUID().toString()); //把消息放入ROUTINGKEY_A对应的队列当中去,对应的是队列A rabbitTemplate.convertAndSend(RabbitConfig2.EXCHANGE_A, RabbitConfig2.ROUTINGKEY_A, content, correlationId); } /** * 回调 */ @Override public void confirm(CorrelationData correlationData, boolean ack, String cause) { log.info(" 回调id:" + correlationData); if (ack) { log.info("消息成功消费"); } else { log.info("消息消费失败:" + cause); } } }
消费者:
package org.rsp; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Slf4j @Component public class TestConsumer { @RabbitListener(queues = "spring-queue") public void test(Message message){ log.info("收到下消息:"+message); } @RabbitListener(queues = "QUEUE_A") public void test2(String content){ log.info("收到下消息:"+content); } }
发送消息的接口
package org.rsp; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.Message; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Slf4j @Component public class TestConsumer { @RabbitListener(queues = "spring-queue") public void test(Message message){ log.info("收到下消息:"+message); } @RabbitListener(queues = "QUEUE_A") public void test2(String content){ log.info("收到下消息:"+content); } }
执行发送消息查看管理控制台
再查看 消费端的 控制台信息可以看到信息已经被消费了
至此 镜像集群的安装 链接 以及简单的代码演示完成
完整代码路径
https://github.com/wanglei111000/rabbitMqMirrorQueen
3.3 高可用集群
借鉴的网图,能说明我们想要搭建的高可用集群就可以了
在3.2中这种集群还有缺点 ,就是当我们的集群节点很多的时候,在做代码开发的时候,需要要在代码中写很多链接的IP信息,然而在很多大型的公司里面 这是不可取的,我们只想在代码里面写一个ip ,由负载均Haproxy 和 keppalived 来实现 ip 的漂移和故障转移.
按照架构图 三个镜像队列我们已经准备好了 ,还需要 两个 haproxy 和keepalive
3.3.1Haproxy 安装
https://www.haproxy.org/#down HAProxy 官网
https://src.fedoraproject.org/repo/pkgs/haproxy/ 镜像网站
tar -zxvf haproxy-2.4.8.tar.gz -C /usr/local
进入解压后根目录,执行下面的编译命令:
cd /usr/local
mkdir haproxy
cd haproxy-2.4.8
make TARGET=linux-glibc PREFIX=/usr/local/haproxy
make install PREFIX=/usr/local/haproxy
配置环境变量:vim /etc/profile
export HAPROXY_HOME=/usr/local/haproxy
export PATH=$PATH:$HAPROXY_HOME/sbin
使得配置的环境变量立即生效
source /etc/profile
新建配置文件 haproxy.cfg,位置为:/etc/haproxy/haproxy.cfg,文件内容如下
# 全局配置
global
# 日志输出配置、所有日志都记录在本机,通过 local0 进行输出
log 127.0.0.1 local0 info
# 最大连接数
maxconn 4096
# 改变当前的工作目录
chroot /usr/local/haproxy
# 以指定的 UID 运行 haproxy 进程
uid 99
# 以指定的 GID 运行 haproxy 进程
gid 99
# 以守护进行的方式运行
daemon
# 当前进程的 pid 文件存放位置
pidfile /usr/local/haproxy/haproxy.pid
# 默认配置
defaults
# 应用全局的日志配置
log global
# 使用4层代理模式,7层代理模式则为"http"
mode tcp
# 日志类别
option tcplog
# 不记录健康检查的日志信息
option dontlognull
# 3次失败则认为服务不可用
retries 3
# 每个进程可用的最大连接数
maxconn 2000
# 连接超时
timeout connect 5s
# 客户端超时
timeout client 120s
# 服务端超时
timeout server 120s
# 绑定配置
listen rabbitmq_cluster
bind :5671
# 配置TCP模式
mode tcp
# 采用加权轮询的机制进行负载均衡
balance roundrobin
# RabbitMQ 集群节点配置
server node1 basic:5672 check inter 5000 rise 2 fall 3 weight 1
server node2 basic02:5672 check inter 5000 rise 2 fall 3 weight 1
server node3 basic03:5672 check inter 5000 rise 2 fall 3 weight 1
# 配置监控页面
listen monitor
bind :8100
mode http
option httplog
stats enable
stats uri /stats
stats refresh 5s
查看 配置 cat /etc/haproxy/haproxy.cfg
负载均衡的主要配置在 listen rabbitmq_cluster 下,这里指定负载均衡的方式为加权轮询,同时定义好健康检查机制:
server node1 basic:5672 check inter 5000 rise 2 fall 3 weight 1
以上配置代表对地址为 basic:5672 的 node1 节点每隔 5 秒进行一次健康检查,如果连续两次的检查结果都是正常,则认为该节点可用,此时可以将客户端的请求轮询到该节点上;如果连续 3 次的检查结果都不正常,则认为该节点不可用。weight 用于指定节点在轮询过程中的权重
启动haproxy服务
haproxy -f /etc/haproxy/haproxy.cfg
查看 Haproxy 启动状态
http://192.168.217.128:8100/stats
http://192.168.217.135:8100/stats
可以看到发送消费消息数量已经被监控到
haProxy 安装完成
3.3.2: keepalive 安装配置
yum install -y keepalived
rpm -ql keepalived 查看 安装配置位置
cp /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.bak 备份配置文件
修改 basic 中的 keepalived.conf
echo "" > keepalived.conf
vim keepalived.conf 添加如下内容
global_defs {
# 路由id,主备节点不能相同
router_id node1
}
# 自定义监控脚本
vrrp_script chk_haproxy {
# 脚本位置
script "/etc/keepalived/haproxy_check.sh"
# 脚本执行的时间间隔
interval 5
weight 10
}
vrrp_instance VI_1 {
# Keepalived的角色,MASTER 表示主节点,BACKUP 表示备份节点
state MASTER
# 指定监测的网卡,可以使用 ifconfig 进行查看
interface ens32
# 虚拟路由的id,主备节点需要设置为相同
virtual_router_id 1
# 优先级,主节点的优先级需要设置比备份节点高
priority 100
# 设置主备之间的检查时间,单位为秒
advert_int 2
# 定义验证类型和密码
authentication {
auth_type PASS
auth_pass w123456
}
# 调用上面自定义的监控脚本
track_script {
chk_haproxy
}
virtual_ipaddress {
# 虚拟IP地址,可以设置多个
192.168.217.200
}
}
修改 basic03 中的 keepalived.conf
echo "" > keepalived.conf
vim keepalived.conf 添加如下内容
global_defs {
# 路由id,主备节点不能相同
router_id node3
}
vrrp_script chk_haproxy {
script "/etc/keepalived/haproxy_check.sh"
interval 5
weight 10
}
vrrp_instance VI_1 {
# BACKUP 表示备份节点
state BACKUP
interface ens32
virtual_router_id 1
# 优先级,备份节点要比主节点低
priority 50
advert_int 2
authentication {
auth_type PASS
auth_pass w123456
}
track_script {
chk_haproxy
}
virtual_ipaddress {
192.168.217.200
}
}
cd /etc/keepalived/ 进入文件夹
分别在 basic 和 basic03 机器的 /etc/keepalived/ 编写一个文件haproxy_check.sh 内容是一致的
#!/bin/bash
# 判断haproxy是否已经启动
if [ ${ps -C haproxy --no-header |wc -l} -eq 0 ] ; then
#如果没有启动,则启动
haproxy -f /etc/haproxy/haproxy.cfg
fi
#睡眠3秒以便haproxy完全启动
sleep 3
#如果haproxy还是没有启动,此时需要将本机的keepalived服务停掉,以便让VIP自动漂移到另外一台haproxy
if [ ${ps -C haproxy --no-header |wc -l} -eq 0 ] ; then
systemctl stop keepalived
fi
创建后为其赋予执行权限: chmod +x /etc/keepalived/haproxy_check.sh
分别在 basic 和 basic03 上启动 KeepAlived 服务
service keepalived start 开启服务
systemctl stop keepalived 关闭服务
使用 ip a 命令查看到虚拟 IP 的情况
模拟basic 下线 ,虚拟ip 转移到basic03
重启 basic 和观察状态 会自动将虚拟ip 切回 ,而basic03 将自动切换为备份节点状态
自此 keepalived + haproxy + rabbitmq 高可用集群 搭建完成
3.3.3: 代码验证高可用集群
将我们之前直接连接镜像集群的代码 稍微做一点更改,然后启动服务 ,不停的发送消息
启动日志中可以发现 连接上了虚拟节点
可以看到 消息可以正常发送和接受
再查看 Haproxy 发现两个 haproxy 的节点上 收到了 不同的请求次数,说明负载均衡已经生效
现在将 basic 的节点 keepalived 下线 验证 是否可以正常发送和接受消息
service keepalived stop
查看 basic03 状态 ,虚拟节ip 转移 了
发消息 检查结果 ,发现 任然可以访问
其他情况 请自行验证 ,到此 高可用集群 搭建验证完毕
最后
以上就是飘逸项链为你收集整理的RabbitMQ HAProxy +Keepalived 高可用集群1:环境准备 2:Rabbitmq 安装3: 集群安装的全部内容,希望文章能够帮你解决RabbitMQ HAProxy +Keepalived 高可用集群1:环境准备 2:Rabbitmq 安装3: 集群安装所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复