之前简单介绍了CentOS下单机部署RabbltMQ环境的操作记录,下面详细说下RabbitMQ集群知识,RabbitMQ是用erlang开发的,集群非常方便,因为erlang天生就是一门分布式语言,但其本身并不支持负载均衡。

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取数据时临时拉取。
-> 该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。
-> 所以在对可靠性要求较高的场合中适用于该模式(比如下面图中介绍该种集群模式)。

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

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

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

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

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

配置RabbitMQ集群非常简单,只需要几个命令,如下面范例,简单说下配置的几个步骤:
第一步:queue、kevintest1、kevintest2做为RabbitMQ集群节点,分别安装RabbitMq-Server ,安装后分别启动RabbitMq-server。

  1. 启动命令
  2. # Rabbit-Server start

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

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

第三步:设置每个节点Cookie

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

第四步:停止所有节点RabbitMq服务,然后使用detached参数独立运行,这步很关键,尤其增加节点停止节点后再次启动遇到无法启动,都可以参照这个顺序

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

第五步:将kevintest1、kevintest2作为内存节点与queue连接起来,在kevintest1上,执行如下命令:

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

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

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

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

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

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

=============清理RabbitMQ消息队列中的所有数据============

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

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

Centos6.9下RabbitMQ集群部署记录的更多相关文章

  1. Elasticsearch学习总结 (Centos7下Elasticsearch集群部署记录)

    一.  ElasticSearch简单介绍 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful web接口.Elasticse ...

  2. Centos6下zookeeper集群部署记录

    ZooKeeper是一个开放源码的分布式应用程序协调服务,它包含一个简单的原语集,分布式应用程序可以基于它实现同步服务,配置维护和命名服务等. Zookeeper设计目的 最终一致性:client不论 ...

  3. RocketMQ集群部署记录

    RocketMQ集群部署记录 #引用    https://cloud.tencent.com/developer/article/1147765         一.RocketMQ基础知识介绍 A ...

  4. rabbitmq集群部署及配置

    消息中间件rabbitmq,一般以集群方式部署,主要提供消息的接受和发送,实现各微服务之间的消息异步.本篇将以rabbitmq+HA方式进行部署. 一.原理介绍 rabbitmq是依据erlang的分 ...

  5. openstack高可用集群21-生产环境高可用openstack集群部署记录

    第一篇 集群概述 keepalived + haproxy +Rabbitmq集群+MariaDB Galera高可用集群   部署openstack时使用单个控制节点是非常危险的,这样就意味着单个节 ...

  6. rabbitMQ集群部署以及集群之间同步

    MQ集群部署 期待的部署架构 其中,一个机房有两台机器部署MQ,并组成集群,有一个机房的MQ集群作为中心集群,其他机房的MQ集群将消息同步到中心MQ集群中. 安装erlang,略.. 安装rabbit ...

  7. redis CentOS6.5安装及集群部署

    .下载redis source包 链接:https://pan.baidu.com/s/122ZCjNvjl9Jx6M2YsLrncw 密码:92ze 2.解压 tar -xzf redis-3.2. ...

  8. CentOS 7 下 RabbitMQ 集群搭建

    环境 10.0.0.20 node1 10.0.0.21 node2 10.0.0.22 node3 搭建(在所有节点执行) 添加EPEL源 [root@node1 ~]# rpm -Uvh http ...

  9. 160328、rabbitMQ集群部署示例

    环境:Centos 6.5 x86_64MQ网址:http://www.rabbitmq.com/SERVER101\SERVER102 SERVER103 一.单节点安装 #yum install ...

随机推荐

  1. C#语言————拼接、插入、替换、删除四种方法

    StringBuilder sb = new StringBuilder("hello"); sb.Append("world");//拼接 sb.Insert ...

  2. late_initcall和module_init的区别

    在init.h中有如下定义: 详情参照:linux 设备驱动加载的先后顺序 #define pure_initcall(fn) __define_initcall("0",fn,1 ...

  3. NFS常见问题

    问题一:取消挂载失败 问题现象: umount /opt/data umount.nfs: /opt/data: device is busy umount.nfs: /opt/data: devic ...

  4. win7系统保护配置现错误“文件名、目录名或卷标语法不正确。(0x8007007B)

    windows7下系统保护功能很是鸡肋,有事会出现一下两个问题: 1.出现错误“文件名.目录名或卷标语法不正确.(0x8007007B) 2.保护设置列表中出现“Windows7_os(c:)(找不到 ...

  5. ios 百度地图使用

    第一步.引入 1.下载SDK  地址http://developer.baidu.com/map/index.php?title=iossdk/sdkiosdev-download 2.解压出Baid ...

  6. 个人技术博客--团队Git规范(参考西瓜学长)

    援引西瓜学长:GitHub团队项目合作流程 废话少说直接写 1.fork 1.对于组员来说第一步就是fork 2.点击fork之后 上面是我们的团队仓库 切换回自己的仓库 就会看到 是fork于团队仓 ...

  7. golang中的init函数以及main函数

    首先我们看一个例子:init函数: init 函数可在package main中,可在其他package中,可在同一个package中出现多次. main函数 main 函数只能在package ma ...

  8. MDC的使用(Mapped Diagnostic Context)的使用

    通常我们可能会有大量的任务需要提交提交到线程池执行,但是此时如果不对日志添加唯一标识进行区分的话回到错乱一坨无法进行查看.因此可以对每一天日志添加唯一的标识,例如使用userid作为日志的唯一标志.这 ...

  9. 接上篇elasticsecrchi 进行搜索及时提示,数据库以及后台代码

    -- ------------------------------ Table structure for articles-- ----------------------------DROP TA ...

  10. mysql explain(转)

    explain显示了mysql如何使用索引来处理select和表连接 转自http://blog.csdn.net/zhuxineli/article/details/14455029 explain ...