RabbitMQ集群搭建-镜像模式

服务器介绍

node1:192.168.174.10
node2:192.168.174.11
node3:192.168.174.12
node4:192.168.174.13
node5:192.168.174.14
其中,node1、node2、node3三台服务器安装RabbitMQ服务,node4和node5安装HA-proxy和Keepalived。

服务集群架构

  • HA-proxy


    Haproxy 介绍

以常见的TCP应用为例,负载均衡器在接收到第一个来自客户端的SYN请求时,会通过设定的负载均衡算法选择一个最佳的后端服务器,同时将报文中目标IP地址修改为后端服务器IP,然后直接转发给该后端服务器,这样一个负载均衡请求就完成了。从这个过程来看,一个TCP连接是客户端和服务器直接建立的,而负载均衡器只不过完成了一个类似路由器的转发动作。在某些负载均衡策略中,为保证后端服务器返回的报文可以正确传递给负载均衡器,在转发报文的同时可能还会对报文原来的源地址进行修改。整个过程下图所示

Haproxy 的特点是:高可用,负载均衡。

  • KeepAlived


    KeepAlived 介绍

KeepAlived 的特点:通过VRRP协议(虚拟ip)实现高可用功能(主备切换)。

KeepAlived 高可用原理

注意:master节点恢复时,是否重新接管master角色,看我们自己的配置,后面配置KeepAlived会讲。

  • 镜像模式
    镜像模式,是中小型企业常用的rabbitmq集群架构:
    镜像模式架构图

    消息的发布(除了Basic.Publish之外)与消费都是通过master节点完成。master节点对消息进行处理的同时将消息的处理动作通过GM(Guarenteed Multicast)广播给所有的slave节点,slave节点的GM收到消息后,通过回调交由mirror_queue_slave进行实际的处理。
    镜像模式流程:程序(Springboot Application)通过访问 KeepAlived 提供的VIP(虚拟ip)指定到其中一个HA-proxy,然后 HA-proxy将访问请求代理到其管理的三个(或多个)rabbitmq server 中的一个,从而实现了高可用、负载均衡的功能。

RabbitMQ主从配置

  • RabbitMQ安装(node1,node2,node3)
    首先配置5个服务器hosts文件:
192.168.174.10  node1
192.168.174.11  node2
192.168.174.12  node3
192.168.174.13  node4
192.168.174.14  node5

1、安装gcc环境

yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel libxml2-utils libxml2 libxslt openssl-devel unixODBC unixODBC-devel unixODBC-bin gtk2 fop gtk2-devel binutils-devel mesa-libGLU-devel yum -y install make gcc gcc-c++ kernel-devel m4 ncurses-devel libxml2-utils libxml2 libxslt openssl-devel unixODBC unixODBC-devel unixODBC-bin gtk2 fop gtk2-devel binutils-devel mesa-libGLU-devel

2、安装erlang
下载地址为:http://www.erlang.org/downloads,我这里下载的是otp_src_20.1.tar.gz
解压、配置、编译:

tar -xvf otp_src_20.1.tar.gz
cd otp_src_20.1
./configure --prefix=/usr/local/erlang20 --without-javac
make && make install

如果报 Java compiler disabled by user 错误,则去掉--without-javac
3、安装 RabbitMQ
安装 python

yum install python -y

安装 simplejson

yum install xmlto -y
yum install python-simplejson -y

rabbitmq下载地址:http://www.rabbitmq.com/download.html,我这里下载的是rabbitmq-server-generic-unix-3.6.14.tar
解压,并移至/usr/local/rabbitmq

tar -xvf rabbitmq-server-generic-unix-3.6.14.tar
mv rabbitmq_server-3.6.14 /usr/local/rabbitmq

设置环境变量

export PATH=$PATH:/usr/local/erlang20/bin:/usr/local/rabbitmq/sbin
source /etc/profile

启动rabbitmq

./rabbitmq-server &
加上& 就是后台启动,./rabbitmqctl stop 为停止服务

设置guest可以远程连接
修改rabbitmq的配置/usr/local/rabbitmq/etc/rabbitmq/rabbitmq.config(没有就新建)
添加:

[{rabbit, [{loopback_users, []}]}].

启用管理控制台

./rabbitmq-plugins enable rabbitmq_management

重启 rabbitmq,打开浏览器访问:http://node1:15672,用户名guest,密码guest。node2和node3安装略。

rabbitmq 管理台

  • RabbitMQ集群配置
    我们这里以node1为master节点,node2和node3为slave节点。
    1、停止MQ服务

rabbimqctl stop

2、复制node1节点的/root/.erlang.cookie文件到其他节点,并覆盖

scp /root/.erlang.cookie root@node2:~
scp /root/.erlang.cookie root@node3:~

3、启动集群

rabbitmq-server -datached

4、slave 加入集群,对node2和node3分别执行下面操作

rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@node1
rabbitmqctl start_app

如果需要移除集群节点,执行下面命令:

rabbitmqctl forget_cluster_node rabbit@node2(具体节点)

5、修改集群名称(任意一个节点操作,默认为master node名称)

rabbitmqctl set_cluster_name rabbitmq_cluster1

6、查看集群状态(任意一个节点操作)

rabbitmqctl cluster_status

7、设置镜像队列策略(任意一个节点操作)

rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'

将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态一致。
此时看rabbitmq管控台,Nodes会有三个节点:


rabbitmq 集群

安装 Haproxy(node4和node5)

1、下载依赖包

yum install gcc

2、下载haproxy

yum install haproxy -y

3、编辑 haproxy 配置文件

vi /etc/haproxy/haproxy.cfg

新增listen内容,根据实际情况,修改default内容:

#logging options
global
    log 127.0.0.1 local0 info
    maxconn 5120
    chroot /usr/local/haproxy
    uid 99
    gid 99
    daemon
    quiet
    nbproc 20
    pidfile /var/run/haproxy.pid
    
defaults
    log global
    # 使用四层代理模式,"mode http" 为7层代理模式
    mode tcp
    # if you set mode to tcp,then you must change tcplog into httplog
    option tcplog
    option dontlognull
    retries 3
    option redispatch
    maxconn 2000
    contimeout 5s
    # 客户端空闲超时时间为60秒,过了该时间,HA发起重连机制
    clitimeout 60s
    # 服务端连接超时时间为15秒,过了该时间,HA发起重连机制
    srvtimeout 15s

listen rabbitmq_cluster
    # 定义监听地址和端口,本机的5672端口
    bind 0.0.0.0:5672
    # 配置 tcp 模式
    mode tcp
    # balance url_param userid
    # balance url_param session_id check_post 64
    # 简单的轮询
    balance roundrobin
    #rabbitmq集群节点配置 #inter 每隔五秒对mq集群做健康检查,2次正确证明服务器可用,
    #2次失败证明服务器不可用,并且配置主备机制
    server node1 192.168.174.10:5672 check inter 5000 rise 2 fall 2
    server node2 192.168.174.11:5672 check inter 5000 rise 2 fall 2
    server node3 192.168.174.12:5672 check inter 5000 rise 2 fall 2
        
# 配置 haproxy web 监控,查看统计信息
listen stats
    bind *:8100
    mode http
    option httplog
    stats enable
    # 设置 haproxy 监控地址为:http://localhost:8100/rabbitmq-stats
    stats uri /rabbitmq-stats
    stats refresh 5s

4、启动haproxy

haproxy -f /etc/haproxy/haproxy.cfg

重启haproxy:service haproxy restart
至此,haproxy配置成功,可以访问:http://192.168.174.13:8100/rabbitmq-stats,可以看到:

haproxy 监控台

安装 Keepalived(node4和node5)

我这里将node4作为keepalived的主节点,node5为备用节点。并且node4宕机恢复服务后,需要抢回VIP。
1、安装所需软件包

yum install -y openssl openssl-devel

2、下载 keepalived

wget http://www.keepalived.org/software/keepalived-1.2.18.tar.gz

3、解压、编译、安装

tar -xvf keepalived-1.2.18.tar.gz
cd keepalived-1.2.18
./configure --prefix=/usr/local/keepalived
make && make install

4、创建文件夹,将keepalived配置文件进行复制

mkdir /etc/keepalived
cp /usr/local/keepalived/etc/rc.d/init.d/keepalived /etc/init.d
cp /usr/local/keepalived/etc/sysconfig/keepalived /etc/sysconfig

5、创建软连接,如果存在则进行删除

ln -s /usr/local/sbin/keepalived /usr/sbin
ln -s /usr/local/keepalived/sbin/keepalived /sbin

6、设置开机启动

chkconfig keepalived on

7、编辑 keepalived 配置文件

vi /etc/keepalived/keepalived.conf

node4的内容如下:

! Configuration File for keepalived

global defs {
    router_id node4 ##标识节点的字符串,通常为hostname
}

vrrp_script chk_haproxy{
    script "/etc/keepalived/haproxy_check.sh"   ## 执行脚本位置
    interval 2  ##检查时间间隔
    weight -20 ##如果条件成立则权重减20
}

vrrp_instance VI_1 {
    state MASTER##主节点为MASTER,备份节点为BACKUP
    interface ens33 ##绑定虚拟ip的网络接口(网卡)
    virtual_router_id 13    ##虚拟路由id号,主备节点相同
    mcast_src_ip 192.168.174.13 ##本机ip地址
    priority 100    ##优先级(0-254)
    nopreempt
    advert_int 1    ##组播信息发送间隔,两个节点必须一致,默认1s
    authentication {    ##认证匹配
        auth_type PASS
        auth_pass bhz
    }
    track_script {
        chk_haproxy
    }
    virtual_ipaddress {
        192.168.174.70 ##虚拟ip,可以指定多个
    }
}

node5的内容如下:

! Configuration File for keepalived

global defs {
    router_id node5 ##标识节点的字符串,通常为hostname
}

vrrp_script chk_haproxy{
    script "/etc/keepalived/haproxy_check.sh"   ## 执行脚本位置
    interval 2  ##检查时间间隔
    weight -20 ##如果条件成立则权重减20
}

vrrp_instance VI_1 {
    state BACKUP ##主节点为MASTER,备份节点为BACKUP
    interface ens33 ##绑定虚拟ip的网络接口(网卡)
    virtual_router_id 13    ##虚拟路由id号,主备节点相同
    mcast_src_ip 192.168.174.14 ##本机ip地址
    priority 90 ##优先级(0-254)
    nopreempt
    advert_int 1    ##组播信息发送间隔,两个节点必须一致,默认1s
    authentication {    ##认证匹配
        auth_type PASS
        auth_pass bhz
    }
    track_script {
        chk_haproxy
    }
    virtual_ipaddress {
        192.168.174.70 ##虚拟ip,可以指定多个
    }
}

vrrp_instance 的 interface 为VIP需要挂载的网卡上,我这里都放在虚拟机的ens33上。 node4 的 state 为 MASTER,node5 为 BACKUP ,priority 要保证node4大于node5,这样就能实现node4宕机之后恢复服务,能够从node5抢回VIP;如果需要实现不抢回VIP,则node4和node5的state都设置为BACKUP,并且vrrp_instance 都添加nopreempt,表示不抢夺VIP(实际上已经加了)。
8、添加执行脚本 haproxy_check.sh

vi /etc/keepalived/haproxy_check.sh

内容如下(node4和node5一样):

#!/bin/bash
COUNT = `ps -C haproxy --no-header | wc -l`
if [$COUNT -eq 0];then
    /usr/local/haproxy/sbin/haproxy -f /etc/haproxy/haproxy.cfg
    sleep 2
    if[`ps -C haproxy --no-header | wc -l` -eq 0];then
        killall keepalived
    fi
fi

9、赋予脚本执行权限

chmod +x haproxy_check.sh

10、启动keepalived

service keepalived start

至此,基于Keepalived和Haproxy的rabbitmq集群,已经搭接完成。
下面我们来测试下keepalived的VIP切换:
当node4和node5都成功启动keepalived时,我们使用命令ip a查看当前服务器的ip:
node4:


node4 master

node5:


node5 backup

此时,VIP落在了node4上,所以node4为master节点,node5为备用节点。
现在,我们让node4的keepalived宕机:
node4 宕机

node5:
node5 夺取vip

当node4的keepalived宕机之后,VIP就被node5拿去了,这样就实现了主备切换的功能。
现在我们让node4的keepalived服务恢复:


node4 恢复服务

当node4恢复服务时,它就会从node5中夺回VIP,重新作为MASTER节点。

集群恢复与故障转移

场景1:


场景1

由于节点B是后停的,所以数据是最新的,并且B是Mater节点。所以先启动B,再启动A即可;如果A(slave)先启动,它会有30s的等待时间,等待master的启动,然后加入cluster中(如果30s内master没有启动,slave会自动停止)。
场景2:


场景2

当所有节点因故障(断电等)同时离线时,每个节点都认为自己不是最后一个停止的节点。要恢复镜像队列,可以尝试在30s之内启动所有节点。
场景3:
场景3

由于A无法恢复,于是需要弃用A,因为B是Master并且是可以恢复的,于是我们可以启动B,然后执行:rabbitmqctl forget_cluster_node A,解除与A的cluster关系。再将新的slave节点加入B即可重新恢复镜像队列。
场景4:


场景4

由于B是Master,但是无法启动,于是作为Slave的A,也是无法启动的。因为如果slave在30s内没有监听到master的信息,则会自行断开。所以,我们需要线下去掉B,执行:rabbitmqctl forget_cluster_node B --offline。
场景5:
场景5

由于A、B都无法恢复,于是我们都得弃用。我们拿到A或者B的磁盘文件,copy到新的服务器对应的目录下。
场景6:
场景6

场景6,无解!!!

彩蛋:

Rabbitmq 集群原理:


Rabbitmq Cluster

上面图中采用三个节点组成了一个RabbitMQ的集群,Exchange A(交换器)的元数据信息在所有节点上是一致的,而Queue(存放消息的队列)的完整数据则只会存在于它所创建的那个节点上。其他节点只知道这个queue的元数据信息和一个指向queue的 owner node 的指针。

客户端直接连接队列所在节点

如果有一个消息生产者或者消息消费者通过amqp-client的客户端连接至节点1进行消息的发布或者订阅,那么此时的集群中的消息收发只与节点1相关。

客户端连接的是非队列数据所在节点

如果消息生产者所连接的是节点2或者节点3,此时队列1的完整数据不在该两个节点上,那么在发送消息过程中这两个节点主要起了一个路由转发作用,根据这两个节点上的元数据转发至节点1上,最终发送的消息还是会存储至节点1的队列1上。同样,如果消息消费者所连接的节点2或者节点3,那这两个节点也会作为路由节点起到转发作用,将会从节点1的队列1中拉取消息进行消费。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容