Centos6.9下RabbitMQ集群部署记录

以前简单介绍了CentOS下单机部署RabbltMQ环境的操做记录,下面详细说下RabbitMQ集群知识,RabbitMQ是用erlang开发的,集群很是方便,由于erlang天生就是一门分布式语言,但其自己并不支持负载均衡。html

Rabbit集群模式大概分为如下三种:单一模式、普通模式、镜像模式,其中:
1)单一模式:最简单的状况,非集群模式,没什么好说的。
2)普通模式:默认的集群模式。
-> 对于Queue来讲,消息实体只存在于其中一个节点,A、B两个节点仅有相同的元数据,即队列结构。
-> 当消息进入A节点的Queue中后,consumer从B节点拉取时,RabbitMQ会临时在A、B间进行消息传输,把A中的消息实体取出并通过B发送给consumer。
-> 因此consumer应尽可能链接每个节点,从中取消息。即对于同一个逻辑队列,要在多个节点创建物理Queue。不然不管consumer连A或B,出口总在A,会产生瓶颈。
-> 该模式存在一个问题就是当A节点故障后,B节点没法取到A节点中还未消费的消息实体。
-> 若是作了消息持久化,那么得等A节点恢复,而后才可被消费;若是没有持久化的话,而后就没有而后了。
3)镜像模式:把须要的队列作成镜像队列,存在于多个节点,属于RabbitMQ的HA方案。
-> 该模式解决了上述问题,其实质和普通模式不一样之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。
-> 该模式带来的反作用也很明显,除了下降系统性能外,若是镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通信大大消耗掉。
-> 因此在对可靠性要求较高的场合中适用于该模式(好比下面图中介绍该种集群模式)。node

RabbitMQ集群中的基本概念:
1)RabbitMQ的集群节点包括内存节点、磁盘节点。顾名思义内存节点就是将全部数据放在内存,磁盘节点将数据放在磁盘。不过,如前文所述,若是在投递消息时,打开了消息的持久化,那么即便是内存节点,数据仍是安全的放在磁盘。
2)一个rabbitmq集 群中能够共享 user,vhost,queue,exchange等,全部的数据和状态都是必须在全部节点上复制的,一个例外是,那些当前只属于建立它的节点的消息队列,尽管它们可见且可被全部节点读取。rabbitmq节点能够动态的加入到集群中,一个节点它能够加入到集群中,也能够从集群环集群会进行一个基本的负载均衡。nginx

RabbitMQ集群中有两种节点:
1)Ram内存节点:只保存状态到内存(一个例外的状况是:持久的queue的持久内容将被保存到disk)
2)Disk磁盘节点:保存状态到内存和磁盘。
内存节点虽然不写入磁盘,可是它执行比磁盘节点要好。RabbitMQ集群中,只须要一个磁盘节点来保存状态就足够了;若是集群中只有内存节点,那么不能中止它们,不然全部的状态,消息等都会丢失。web

RabbitMQ集群思路:
那么具体如何实现RabbitMQ高可用,咱们先搭建一个普通集群模式,在这个模式基础上再配置镜像模式实现高可用,Rabbit集群前增长一个反向代理,生产者、消费者经过反向代理访问RabbitMQ集群。redis

上图中3个RabbitMQ运行在同一主机上,分别用不一样的服务端口。固然在生产环境里,多个RabbitMQ确定是运行在不一样的物理服务器上,不然就失去了高可用的意义。api

RabbitMQ集群模式配置
该设计架构能够以下:在一个集群里,有3台机器,其中1台使用磁盘模式,另2台使用内存模式。2台内存模式的节点,无疑速度更快,所以客户端(consumer、producer)链接访问它们。而磁盘模式的节点,因为磁盘IO相对较慢,所以仅做数据备份使用,另一台做为反向代理。安全

配置RabbitMQ集群很是简单,只须要几个命令,以下面范例,简单说下配置的几个步骤:
第一步:queue、kevintest一、kevintest2作为RabbitMQ集群节点,分别安装RabbitMq-Server ,安装后分别启动RabbitMq-server。bash

1
2
启动命令 
# Rabbit-Server start

第二步:在安装好的三台节点服务器中,分别修改/etc/hosts文件,指定queue、kevintest一、kevintest2的hosts。服务器

1
2
3
4
5
6
172.16.3.32  queue
172.16.3.107 kevintest1
172.16.3.108 kevintest2
  
三台节点的 hostname 要正确,主机名分别是queue、kevintest一、kevintest2,若是修改 hostname ,建议安装rabbitmq前修改。请注意RabbitMQ集群节点必须在同一个网段里,
若是是跨广域网效果就差。

第三步:设置每一个节点Cookiecookie

1
2
3
4
5
6
7
8
9
10
11
12
Rabbitmq的集群是依赖于erlang的集群来工做的,因此必须先构建起erlang的集群环境。Erlang的集群中各节点是经过一个magic cookie来实现的,这个cookie存放在
/var/lib/rabbitmq/ .erlang.cookie 中,文件是400的权限。因此必须保证各节点cookie保持一致,不然节点之间就没法通讯。
# ll /var/lib/rabbitmq/.erlang.cookie
-r-------- 1 rabbitmq rabbitmq 21 12月  6 00:40  /var/lib/rabbitmq/ .erlang.cookie
 
将queue的 /var/lib/rabbitmq/ .erlang.cookie这个文件,拷贝到kevintest一、kevintest2的同一位置(反过来亦可),该文件是集群节点进行通讯的验证密钥,全部
节点必须一致。拷完后重启下RabbitMQ。复制好后别忘记还原.erlang.cookie的权限,不然可能会遇到错误
# chmod 400 /var/lib/rabbitmq/.erlang.cookie
 
设置好cookie后先将三个节点的rabbitmq重启
# rabbitmqctl stop
# rabbitmq-server start

第四步:中止全部节点RabbitMq服务,而后使用detached参数独立运行,这步很关键,尤为增长节点中止节点后再次启动遇到没法启动,均可以参照这个顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
[root@queue ~] # rabbitmqctl stop
[root@kevintest1 ~] # rabbitmqctl stop
[root@kevintest2 ~] # rabbitmqctl stop
  
[root@queue ~] # rabbitmq-server -detached
[root@kevintest1 ~] # rabbitmq-server -detached
[root@kevintest2 ~] # rabbitmq-server -detached
  
分别查看下每一个节点
[root@queue ~] # rabbitmqctl cluster_status
Cluster status of node rabbit@queue ...
[{nodes,[{disc,[rabbit@queue]}]},
{running_nodes,[rabbit@queue]},
{partitions,[]}]
... done .
  
[root@kevintest1 ~] # rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest1...
[{nodes,[{disc,[rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest1]},
{partitions,[]}]
... done .
 
[root@kevintest2 ~] # rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest2...
[{nodes,[{disc,[rabbit@kevintest2]}]},
{running_nodes,[rabbit@kevintest2]},
{partitions,[]}]
... done .

第五步:将kevintest一、kevintest2做为内存节点与queue链接起来,在kevintest1上,执行以下命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@kevintest1 ~] # rabbitmqctl stop_app
[root@kevintest1 ~] # rabbitmqctl join_cluster --ram rabbit@queue  
[root@kevintest1 ~] # rabbitmqctl start_app
 
[root@kevintest2 ~] # rabbitmqctl stop_app
[root@kevintest2 ~] # rabbitmqctl join_cluster --ram rabbit@queue   #上面已经将kevintest1与queue链接,也能够直接将kevintest2与kevintest1链接,一样而已加入集群中
[root@kevintest2 ~] # rabbitmqctl start_app
 
1)上述命令先停掉rabbitmq应用,而后调用cluster命令,将kevintest1链接到,使二者成为一个集群,最后重启rabbitmq应用。
2)在这个cluster命令下,kevintest一、kevintest2是内存节点,queue是磁盘节点(RabbitMQ启动后,默认是磁盘节点)。
3)queue若是要使kevintest1或kevintest2在集群里也是磁盘节点,join_cluster 命令去掉-- ram 参数便可
#rabbitmqctl join_cluster rabbit@queue  
只要在节点列表里包含了本身,它就成为一个磁盘节点。在RabbitMQ集群里,必须至少有一个磁盘节点存在。

第六步:在queue、kevintest一、kevintest2上,运行cluster_status命令查看集群状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# rabbitmqctl cluster_status
Cluster status of node rabbit@queue ...
[{nodes,[{disc,[rabbit@queue]},{ ram ,[rabbit@kevintest2,rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest2,rabbit@kevintest1,rabbit@queue]},
{partitions,[]}]
... done .
 
[root@kevintest1 rabbitmq] # rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest1 ...
[{nodes,[{disc,[rabbit@queue]},{ ram ,[rabbit@kevintest2,rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest2,rabbit@queue,rabbit@kevintest1]},
{partitions,[]}]
... done .
  
[root@kevintest2 rabbitmq] # rabbitmqctl cluster_status
Cluster status of node rabbit@kevintest2 ...
[{nodes,[{disc,[rabbit@queue]},{ ram ,[rabbit@kevintest2,rabbit@kevintest1]}]},
{running_nodes,[rabbit@kevintest1,rabbit@queue,rabbit@kevintest2]},
{partitions,[]}]
... done .
 
这时能够看到每一个节点的集群信息,分别有两个内存节点一个磁盘节点

第七步:往任意一台集群节点里写入消息队列,会复制到另外一个节点上,咱们看到两个节点的消息队列数一致:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[root@kevintest2 ~] # rabbitmqctl list_queues -p hrsystem
 
Listing queues …
test_queue 10000
done .
 
[root@kevintest1 ~] # rabbitmqctl list_queues -p hrsystem
Listing queues …
test_queue 10000
done .
  
[root@queue ~] # rabbitmqctl list_queues -p hrsystem
Listing queues …
test_queue 10000
done .
  
-p参数为vhost名称

这样RabbitMQ集群就正常工做了,这种模式更适合非持久化队列,只有该队列是非持久的,客户端才能从新链接到集群里的其余节点,并从新建立队列。假如该队列是持久化的,那么惟一办法是将故障节点恢复起来;为何RabbitMQ不将队列复制到集群里每一个节点呢?这与它的集群的设计本意相冲突,集群的设计目的就是增长更多节点时,能线性的增长性能(CPU、内存)和容量(内存、磁盘)。理由以下:固然RabbitMQ新版本集群也支持队列复制(有个选项能够配置)。好比在有五个节点的集群里,能够指定某个队列的内容在2个节点上进行存储,从而在性能与高可用性之间取得一个平衡。

=============清理RabbitMQ消息队列中的全部数据============

1
2
3
4
5
6
方法以下:
# rabbitmqctl list_queues    //查看全部队列数据
# rabbitmqctl stop_app      //要先关闭应用,不然不能清除
# rabbitmqctl reset
# rabbitmqctl start_app
# rabbitmqctl list_queues   //这时候看到listing 及queues都是空的

=========================================================================================

RabbitMQ集群:
1)RabbitMQ broker集群是多个erlang节点的逻辑组,每一个节点运行rabbitmq应用,他们之间共享用户、虚拟主机、队列、exchange、绑定和运行时参数;
2)RabbitMQ集群之间复制什么信息:除了message queue(存在一个节点,从其余节点均可见、访问该队列,要实现queue的复制就须要作queue的HA)以外,任何一个rabbitmq broker上的全部操做的data和state都会在全部的节点之间进行复制;
3)RabbitMQ消息队列是很是基础的关键服务。本文3台rabbitMQ服务器构建broker集群,1个master,2个slave。容许2台服务器故障而服务不受影响。

RabbitMQ集群的目的
1)容许消费者和生产者在RabbitMQ节点崩溃的状况下继续运行
2)经过增长更多的节点来扩展消息通讯的吞吐量

RabbitMQ集群运行的前提:
1)集群全部节点必须运行相同的erlang及rabbitmq版本
2)hostname解析,节点之间经过域名相互通讯,本文为3个node的集群,采用配置hosts的形式。

RabbitMQ端口及用途
1)5672 客户端链接用途
2)15672 web管理接口
3)25672 集群通讯用途

RabbitMQ集群的搭建方式:
1)经过rabbitmqctl手工配置 (本文采用此方式)
2)经过配置文件声明
3)经过rabbitmq-autocluster插件声明
4)经过rabbitmq-clusterer插件声明

RabbitMQ集群故障处理机制:
1)rabbitmq broker集群容许个体节点down机,
2)对应集群的的网络分区问题( network partitions)

RabbitMQ集群推荐用于LAN环境,不适用WAN环境;要经过WAN链接broker,Shovel or Federation插件是最佳的解决方案;Shovel or Federation不一样于集群。

RabbitMQ集群的节点运行模式:
为保证数据持久性,目前全部node节点跑在disk模式,若是从此压力大,须要提升性能,考虑采用ram模式

RabbitMQ节点类型
1)RAM node:内存节点将全部的队列、交换机、绑定、用户、权限和vhost的元数据定义存储在内存中,好处是可使得像交换机和队列声明等操做更加的快速。
2)Disk node:将元数据存储在磁盘中,单节点系统只容许磁盘类型的节点,防止重启RabbitMQ的时候,丢失系统的配置信息。

问题说明: 
RabbitMQ要求在集群中至少有一个磁盘节点,全部其余节点能够是内存节点,当节点加入或者离开集群时,必需要将该变动通知到至少一个磁盘节点。
若是集群中惟一的一个磁盘节点崩溃的话,集群仍然能够保持运行,可是没法进行其余操做(增删改查),直到节点恢复。

解决方案:设置两个磁盘节点,至少有一个是可用的,能够保存元数据的更改。

RabbitMQ集群节点之间是如何相互认证的:
1)经过Erlang Cookie,至关于共享秘钥的概念,长度任意,只要全部节点都一致便可。
2)rabbitmq server在启动的时候,erlang VM会自动建立一个随机的cookie文件。cookie文件的位置是/var/lib/rabbitmq/.erlang.cookie 或者 /root/.erlang.cookie,为保证cookie的彻底一致,采用从一个节点copy的方式。

Erlang Cookie是保证不一样节点能够相互通讯的密钥,要保证集群中的不一样节点相互通讯必须共享相同的Erlang Cookie。具体的目录存放在/var/lib/rabbitmq/.erlang.cookie。
说明:这就要从rabbitmqctl命令的工做原理提及,RabbitMQ底层是经过Erlang架构来实现的,因此rabbitmqctl会启动Erlang节点,并基于Erlang节点来使用Erlang系统链接RabbitMQ节点,在链接过程当中须要正确的Erlang Cookie和节点名称,Erlang节点经过交换Erlang Cookie以得到认证。

=======如下记录CentOS6.9下RabbitMQ集群部署过程=======

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
集群机器信息:
rabbitmq01.kevin.cn      192.168.1.40
rabbitmq02.kevin.cn      192.168.1.41
rabbitmq03.kevin.cn      192.168.1.42
  
1)设置hosts主机解析,rabbitmq 集群通讯用途,全部节点配置相同。
[root@rabbitmq01 ~] # cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.40  rabbitmq01.kevin.cn
192.168.1.41  rabbitmq02.kevin.cn
192.168.1.42  rabbitmq03.kevin.cn
  
其余两个节点的hosts配置一致。
  
2)三台节点服务器上都要部署rabbitmq环境,能够参考:http: //www .cnblogs.com /kevingrace/p/7693042 .html
前台运行rabbitmq服务:
# /etc/init.d/rabbitmq-server start  (用户关闭链接后,自动结束进程)
或者
# rabbitmq-server start   
  
设置开机启动
# chkconfig rabbitmq-server on
   
后台运行rabbitmq服务:
# rabbitmq-server -detached
  
# lsof -i:5672
# lsof -i:15672
# lsof -i:25672
  
查看各节点状态:
# rabbitmqctl status
或者
# /etc/init.d/rabbitmq-server status
  
3)设置节点间认证的cookie。能够把其中一个节点(好比rabbitmq01)的文件使用 scp 拷贝到其余两个节点上
[root@rabbitmq01 ~] # cat /var/lib/rabbitmq/.erlang.cookie
FXQTFVXIUWEBZRLXFQOZ
[root@rabbitmq02 ~] # cat /var/lib/rabbitmq/.erlang.cookie
FXQTFVXIUWEBZRLXFQOZ
[root@rabbitmq03 ~] # cat /var/lib/rabbitmq/.erlang.cookie
FXQTFVXIUWEBZRLXFQOZ
  
同步完cookie以后,重启rabbitmq-server。
# /etc/init.d/rabbitmq-server restart
  
4)为了把集群中的3个节点联系起来,能够将其中两个节点加入到另外一个节点中。
好比:将rabbitmq0一、rabbitmq03分别加入到集群rabbitmq02中,其中rabbitmq01和rabbitmq02节点为内存节点。rabbitmq02为磁盘节点。
  
注意:rabbitmqctl stop_app ---仅关闭应用,节点不被关闭
  
[root@rabbitmq01 ~] # rabbitmqctl stop_app
[root@rabbitmq01 ~] # rabbitmqctl join_cluster --ram rabbit@rabbitmq02
[root@rabbitmq01 ~] # rabbitmqctl start_app
  
[root@rabbitmq03 ~] # rabbitmqctl stop_app
[root@rabbitmq03 ~] # rabbitmqctl join_cluster --ram rabbit@rabbitmq02
[root@rabbitmq03 ~] # rabbitmqctl start_app
  
查看RabbitMQ集群状况(三个节点查看的结果同样)
[root@rabbitmq01 ~] # rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq01 ...
[{nodes,[{disc,[rabbit@rabbitmq02]},
          { ram ,[rabbit@rabbitmq03,rabbit@rabbitmq01]}]},
  {running_nodes,[rabbit@rabbitmq03,rabbit@rabbitmq02,rabbit@rabbitmq01]},
  {cluster_name,<< "rabbit@rabbitmq02.kevin.cn" >>},
  {partitions,[]},
  {alarms,[{rabbit@rabbitmq03,[]},
           {rabbit@rabbitmq02,[]},
           {rabbit@rabbitmq01,[]}]}]
  
RabbitMQ集群的名字默认是第一个节点的名字,好比上面集群的名字是rabbitmq01。
  
修改RabbitMQ集群的名字kevinmq
# rabbitmqctl set_cluster_name kevinmq
# rabbitmqctl cluster_status
  
重启集群:
# rabbitmqctl stop
# rabbitmq-server -detached
# rabbitmqctl cluster_status    //观察集群的运行状态变化
  
5)重要信息:
当整个集群down掉时,最后一个down机的节点必须第一个启动到在线状态,若是不是这样,节点会等待30s等最后的磁盘节点恢复状态,而后失败。
若是最后下线的节点不能上线,能够经过forget_cluster_node 指令来踢出集群。
  
若是全部的节点不受控制的同时宕机,好比掉电,会进入全部的节点都会认为其余节点比本身宕机的要晚,即本身先宕机,这种状况下可使用
force_boot指令来启动一个节点。
  
6)打破集群:
当一个节点不属于这个集群的时候,须要及时踢出,能够经过本地或者远程的方式
# rabbitmqctl stop_app
# rabbitmqctl reset
# rabbitmqctl start_app
  
这样再次查看RabbitMQ集群的时候,该节点就不会在这里面了
# rabbitmqctl cluster_status
  
7)客户端链接集群测试
经过web管理页面进行建立队列、发布消息、建立用户、建立policy等。
http: //192 .168.1.41:15672/
 
或者经过rabbitmqadmin命令行来测试
[root@rabbitmq02 ~] # wget https://192.168.1.41:15672/cli/rabbitmqadmin
[root@rabbitmq02 ~] # chmod +x rabbitmqadmin
[root@rabbitmq02 ~] # mv rabbitmqadmin /usr/sbin/
 
Declare an exchange
[root@rabbitmq02 ~] # rabbitmqadmin declare exchange name=my-new-exchange type=fanout
exchange declared
Declare a queue, with optional parameters
 
[root@rabbitmq02 ~] # rabbitmqadmin declare queue name=my-new-queue durable=false
queue declared
Publish a message
 
[root@rabbitmq02 ~] # rabbitmqadmin publish exchange=my-new-exchange routing_key=test payload="hello, world"
Message published
And get it back
 
[root@rabbitmq02 ~] # rabbitmqadmin get queue=test requeue=false
+-------------+----------+---------------+--------------+------------------+-------------+
| routing_key | exchange | message_count | payload      | payload_encoding | redelivered |
+-------------+----------+---------------+--------------+------------------+-------------+
test         |          | 0             | hello, world | string           | False       |
+-------------+----------+---------------+--------------+------------------+-------------+

测试后发现问题问题:
[root@rabbitmq01 ~]# rabbitmqctl stop_app
[root@rabbitmq01 ~]# rabbitmqctl stop
在stop_app或者stop掉broker以后在rabbitmq01节点的上队列已经不可用了,重启rabbitmq01的app或broker以后,虽然集群工做正常,但rabbitmq01上队列中消息会被清空(queue仍是存在的)

对于生产环境而已,这确定是不可接受的,若是不能保证队列的高可用,那么作集群的意义也不太大了,还好rabbitmq支持Highly Available Queues,下面介绍下queue的HA。

=================Queue HA配置===============

默认状况下,RabbitMQ集群中的队列存在于集群中的单个节点上,这要看建立队列时声明在那个节点上建立,而exchange和binding则默认存在于集群中全部节点。
队列能够经过镜像来提升可用性,HA依赖rabbitmq cluster,因此队列镜像也不适合WAN部署,每一个被镜像的队列包含一个master和一个或者多个slave,当master
因任何缘由故障时,最老的slave被提高为新的master。发布到队列的消息被复制到全部的slave上,消费者不管链接那个node,都会链接到master;若是master确
认要删除消息,那么全部slave就会删除队列中消息。队列镜像能够提供queue的高可用性,但不能分担负载,由于全部参加的节点都作全部的工做。

1. 配置队列镜像
经过policy来配置镜像,策略可在任什么时候候建立,好比先建立一个非镜像的队列,而后在镜像,反之亦然。
镜像队列和非镜像队列的区别是非镜像队列没有slaves,运行速度也比镜像队列快。

设置策略,而后设置ha-mode,3种模式:all、exactly、nodes。
每一个队列都有一个home node,叫作queue master node

1)设置policy,以ha.开头的队列将会被镜像到集群其余全部节点,一个节点挂掉而后重启后须要手动同步队列消息

1
# rabbitmqctl set_policy ha-all-queue "^ha\." '{"ha-mode":"all"}'

2)设置policy,以ha.开头的队列将会被镜像到集群其余全部节点,一个节点挂掉而后重启后会自动同步队列消息(生产环境采用这个方式)

1
# rabbitmqctl set_policy ha-all-queue "^ha\." '{"ha-mode":"all","ha-sync-mode":"automatic"}'

2. 问题:
配置镜像队列后,其中1台节点失败,队列内容是不会丢失,若是整个集群重启,队列中的消息内容仍然丢失,如何实现队列消息内容持久化那?
集群节点跑在disk模式,建立见消息的时候也声明了持久化,为何仍是不行那?

由于建立消息的时候须要指定消息是否持久化,若是启用了消息的持久化的话,重启集群消息也不会丢失了,前提是建立的队列也应该是建立的持久化队列。

客户端链接rabbitMQ集群服务的方式:
1)客户端能够链接集群中的任意一个节点,若是一个节点故障,客户端自行从新链接到其余的可用节点;(不推荐,对客户端不透明)
2)经过动态DNS,较短的ttl
3)经过HA+4层负载均衡器(好比haproxy+keepalived)

==========Haproxy+keepalived的部署===============
消息队列做为公司的关键基础服务,为给客户端提供稳定、透明的rabbitmq服务,现经过Haproxy+keepalived构建高可用的rabbitmq统一入口,及基本的负载均衡服务。
为简化安装配置,现采用yum的方式安装haproxy和keepalived,可参考 基于keepalived+nginx部署强健的高可用7层负载均衡方案。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
在两台两台服务器部署haproxy+Keepalived环境,部署过程同样。
haroxy01.kevin.cn      192.168.1.43
haroxy02.kevin.cn      192.168.1.44
 
1)安装
[root@haproxy01 ~] # yum install haproxy keepalived -y
[root@haproxy01 ~] # /etc/init.d/keepalived start
 
2)设置关键服务开机自启动
[root@haproxy01 ~] # chkconfig --list|grep haproxy
[root@haproxy01 ~] # chkconfig haproxy on
[root@haproxy01 ~] # chkconfig --list|grep haproxy
 
3) 配置将haproxy的log记录到  /var/log/haproxy .log
[root@haproxy01 ~] # more /etc/rsyslog.d/haproxy.conf
$ModLoad imudp
$UDPServerRun 514
local0.*  /var/log/haproxy .log
 
[root@haproxy01 ~] # /etc/init.d/rsyslog restart
 
4)haproxy的配置,2台机器上的配置彻底相同
[root@haproxy01 ~] # more /etc/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# https://haproxy.1wt.eu/download/1.4/doc/configuration.txt
#
#---------------------------------------------------------------------
 
 
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
# to have these messages end up in /var/log/haproxy.log you will
# need to:
#
# 1) configure syslog to accept network log events. This is done
# by adding the '-r' option to the SYSLOGD_OPTIONS in
# /etc/sysconfig/syslog
#
# 2) configure local2 events to go to the /var/log/haproxy.log
# file. A line like the following can be added to
# /etc/sysconfig/syslog
#
# local2.* /var/log/haproxy.log
#
log 127.0.0.1 local2 notice
 
chroot  /var/lib/haproxy
pidfile  /var/run/haproxy .pid
maxconn 4000
user haproxy
group haproxy
daemon
 
# turn on stats unix socket
stats socket  /var/lib/haproxy/stats
 
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaults
mode tcp
option tcplog
option dontlognull
option http-server-close
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
 
###haproxy statistics monitor by laijingli 20160222
listen statics 0.0.0.0:8888
mode http
log 127.0.0.1 local0 debug
transparent
stats refresh 60s
stats uri / haproxy-stats
stats realm Haproxy \ statistic
stats auth laijingli:xxxxx
 
#---------------------------------------------------------------------
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend kevin_rabbitMQ_cluster_frontend
mode tcp
option tcpka
log 127.0.0.1 local0 debug
bind 0.0.0.0:5672
use_backend kevin_rabbitMQ_cluster_backend
 
frontend kevin_rabbitMQ_cluster_management_frontend
mode tcp
option tcpka
log 127.0.0.1 local0 debug
bind 0.0.0.0:15672
use_backend kevin_rabbitMQ_cluster_management_backend
 
 
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend kevin_rabbitMQ_cluster_backend
balance roundrobin
server rabbitmq01.kevin.cn 192.168.1.40:5672 check inter 3s rise 1 fall 2
server rabbitmq02.kevin.cn 192.168.1.41:5672 check inter 3s rise 1 fall 2
server rabbitmq03.kevin.cn 192.168.1.42:5672 check inter 3s rise 1 fall 2
 
 
backend kevin_rabbitMQ_cluster_management_backend
balance roundrobin
server rabbitmq01.kevin.cn 192.168.1.40:15672 check inter 3s rise 1 fall 2
server rabbitmq02.kevin.cn 192.168.1.41:15672 check inter 3s rise 1 fall 2
server rabbitmq03.kevin.cn 192.168.1.42:15672 check inter 3s rise 1 fall 2
 
5)keepalived配置,特别注意2台服务器上的keepalived配置不同。
=======================先看下haroxy01.kevin.cn机器上的配置===========================
[root@haproxy01 ~] # more /etc/keepalived/keepalived.conf
global_defs {
notification_email {
wangshibo@kevin.cn
102533678@qq.com
}
notification_email_from notice@kevin.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy43       ## xxhaproxy101 on master , xxhaproxy102 on backup
}
 
 
###simple check with killall -0 which is less expensive than pidof to verify that nginx is running
vrrp_script chk_nginx {
script  "killall -0 nginx"
interval 1
weight 2
fall 2
rise 1
}
 
 
vrrp_instance KEVIN_GATEWAY {
state MASTER               ## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 101          ## KEVIN_GATEWAY virtual_router_id
priority 200             ## 200 on master , 199 on backup
advert_int 1
###采用单播通讯,避免同一个局域网中多个keepalived组之间的相互影响
unicast_src_ip 192.168.1.43      ##本机ip
unicast_peer {
192.168.1.44      ##对端ip
}
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.1.45                   ## VIP
}
###若是只有一块网卡的话监控网络接口就没有必要了
#track_interface {
# em1
#}
track_script {
chk_nginx
}
###状态切换是发送邮件通知,本机记录log,后期会触发短信通知
notify_master  /usr/local/bin/keepalived_notify .sh notify_master
notify_backup  /usr/local/bin/keepalived_notify .sh notify_backup
notify_fault  /usr/local/bin/keepalived_notify .sh notify_fault
notify  /usr/local/bin/keepalived_notify .sh notify
smtp_alert
}
 
###simple check with killall -0 which is less expensive than pidof to verify that haproxy is running
vrrp_script chk_haproxy {
script  "killall -0 haproxy"
interval 1
weight 2
fall 2
rise 1
}
vrrp_instance kevin_rabbitMQ_GATEWAY {
state BACKUP           ## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 111  ## kevin_rabbitMQ_GATEWAY virtual_router_id
priority 199          ## 200 on master , 199 on backup
advert_int 1
###采用单播通讯,避免同一个局域网中多个keepalived组之间的相互影响
unicast_src_ip 192.168.1.43       ##本机ip
unicast_peer {
192.168.1.44         ##对端ip
}
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.1.46         ## VIP
}
###若是只有一块网卡的话监控网络接口就没有必要了
#track_interface {
# em1
#}
track_script {
chk_haproxy
}
###状态切换是发送邮件通知,本机记录log,后期会触发短信通知
notify_master  /usr/local/bin/keepalived_notify_for_haproxy .sh notify_master
notify_backup  /usr/local/bin/keepalived_notify_for_haproxy .sh notify_backup
notify_fault  /usr/local/bin/keepalived_notify_for_haproxy .sh notify_fault
notify  /usr/local/bin/keepalived_notify_for_haproxy .sh notify
smtp_alert
}
 
 
=============================再看下haroxy02.kevin.cn机器上的配置==========================
[root@haproxy02 ~] # more /etc/keepalived/keepalived.conf
global_defs {
notification_email {
wangshibo@kevin.cn
102533678@qq.com
}
notification_email_from notice@kevin.cn
smtp_server 127.0.0.1
smtp_connect_timeout 30
router_id haproxy44      ## xxhaproxy101 on master , xxhaproxy102 on backup
}
 
###simple check with killall -0 which is less expensive than pidof to verify that nginx is running
vrrp_script chk_nginx {
script  "killall -0 nginx"
interval 1
weight 2
fall 2
rise 1
}
 
vrrp_instance KEVIN_GATEWAY {
state BACKUP          ## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 101        ## KEVIN_GATEWAY virtual_router_id
priority 199       ## 200 on master , 199 on backup
advert_int 1
###采用单播通讯,避免同一个局域网中多个keepalived组之间的相互影响
unicast_src_ip 192.168.1.44      ##本机ip
unicast_peer {
192.168.1.43        ##对端ip
}
authentication {
auth_type PASS
auth_pass YN_API_HA_PASS
}
virtual_ipaddress {
192.168.1.45      ## VIP
}
###若是只有一块网卡的话监控网络接口就没有必要了
#track_interface {
# em1
#}
track_script {
chk_nginx
}
###状态切换是发送邮件通知,本机记录log,后期会触发短信通知
notify_master  /usr/local/bin/keepalived_notify .sh notify_master
notify_backup  /usr/local/bin/keepalived_notify .sh notify_backup
notify_fault  /usr/local/bin/keepalived_notify .sh notify_fault
notify  /usr/local/bin/keepalived_notify .sh notify
smtp_alert
}
 
###simple check with killall -0 which is less expensive than pidof to verify that haproxy is running
vrrp_script chk_haproxy {
script  "killall -0 haproxy"
interval 1
weight 2
fall 2
rise 1
}
vrrp_instance kevin_rabbitMQ_GATEWAY {
state MASTER         ## MASTER on master , BACKUP on backup
interface em1
virtual_router_id 111        ## kevin_rabbitMQ_GATEWAY virtual_router_id
priority 200        ## 200 on master , 199 on backup
advert_int 1
###采用单播通讯,避免同一个局域网中多个keepalived组之间的相互影响
unicast_src_ip 192.168.1.44       ##本机ip
unicast_peer {
192.168.1.43       ##对端ip
}
authentication {
auth_type PASS
auth_pass YN_MQ_HA_PASS
}
virtual_ipaddress {
192.168.1.46       ## VIP
}
###若是只有一块网卡的话监控网络接口就没有必要了
#track_interface {
# em1
#}
track_script {
chk_haproxy
}
###状态切换是发送邮件通知,本机记录log,后期会触发短信通知
notify_master  /usr/local/bin/keepalived_notify_for_haproxy .sh notify_master
notify_backup  /usr/local/bin/keepalived_notify_for_haproxy .sh notify_backup
notify_fault  /usr/local/bin/keepalived_notify_for_haproxy .sh notify_fault
notify  /usr/local/bin/keepalived_notify_for_haproxy .sh notify
smtp_alert
}
 
 
配置中用到的通知脚本,2台haproxy服务器上彻底同样:
[root@haproxy01 ~] # more /usr/local/bin/keepalived_notify.sh
#!/bin/bash
###keepalived notify script for record ha state transtion to log files
 
###将将状态转换过程记录到log,便于排错
logfile= /var/log/keepalived .notify.log
echo  --------------- >> $logfile
echo  ` date ` [` hostname `] keepalived HA role state transition: $1 $2 $3 $4 $5 $6 >> $logfile
 
###将状态转换记录到nginx的文件,便于经过web查看ha状态(必定注意不要开放到公网)
echo  ` date ` ` hostname ` $1 $2 $3 $4 $5 $6 "
" >  /usr/share/nginx/html/index_for_nginx .html
 
###将nginx api和rabbitmq的ha log记录到同一个文件里
cat  /usr/share/nginx/html/index_for * >  /usr/share/nginx/html/index .html
 
 
6)haproxy监控页面。
访问地址http: //192 .168.1.43:8888
 
7)查看keepalived中高可用服务运行在那台服务器上
https: //192 .168.1.43
 
8)经过VIP访问rabbitMQ服务
http: //192 .168.1.46:5672
 
9)其余问题
rabbitmq服务客户端使用规范
1)使用vhost来隔离不一样的应用、不一样的用户、不一样的业务组
2)消息持久化,exchange、queue、message等持久化须要在客户端声明指定
相关文章
相关标签/搜索