我是靠谱客的博主 飘逸项链,最近开发中收集的这篇文章主要介绍RabbitMQ HAProxy +Keepalived 高可用集群1:环境准备 2:Rabbitmq 安装3: 集群安装,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

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: 集群安装所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(40)

评论列表共有 0 条评论

立即
投稿
返回
顶部