RabbitMQ消息队列的作为一个消息通知的系统,对于可靠性和性能是非常关键,所以集群也是提升可靠性和性能的一种手段。但是我这里只是会写上基础的RabbitMQ的集群搭建,其实也就是方便我以后能够把命令记回来而已。当然我也会尝试在官网上获得一些关于RabbitMQ集群的官方信息在这里贴出 方便我回忆。
以上的数据除了队列元数据,其他数据均存在所有的节点当中,同时必须至少有一个磁盘节点,其余都可以是内存节点。也就是说磁盘节点是存储着以上的数据在磁盘当中,这些会影响消息的路由,所以当磁盘节点挂了之后,虽然不会影响消息路由但是你已经不能创建队列、创建交换器、添加用户、添加绑定、更改用户权限甚至不能添加或者删除群集节点。所以一般保险起见我们都会选择创建两个磁盘节点从而达到高可用的要求。
但是什么队列不是存在每一个节点当中呢?因为队列的消息也非常频繁的,所以每次你发消息需要分发到这么多个节点当中,这个对性能上有比较大的损耗,所以一般情况下,队列只会存在第一个节点当中,但是整个RabbitMQ cluster都可以访问这个队列,因为路由的信息是存在所有的节点当中,每个节点也晓得如何去获得节点的队列的。当然也队列也可以存在多个节点当中,这种叫做镜像队列。对了如果可能你会问如果队列存在单独的节点当中,如果那个节点挂了怎么办,能怎么办那就挂了呗,那就创建一个新的队列,如果那个队列是一个持久队列,你将不能在其他节点中创建相同的队列,因为每个节点都知道那个节点是持久的节点,需要等待那个节点起来了才能正常使用。所以才有镜像队列这一东西,镜像队列可以有效的解决这个问题,但是镜像队列也不是那么好搞蒂·····
别废话上命令上代码,来点有营养的。
怎么才能链接多台服务器呢,erlang是通过一个叫做erlang-cookie的东西来做认证的,文件里是一堆字符串,所有的节点服务器必须erlang一致才能连接,这个是关于这个erlang-cookie的精简版 详细版我贴出官网的。
RabbitMQ nodes and CLI tools (e.g. rabbitmqctl) use a cookie to determine whether they are allowed to communicate with each other. For two nodes to be able to communicate they must have the same shared secret called the Erlang cookie. The cookie is just a string of alphanumeric characters. It can be as long or short as you like. Every cluster node must have the same cookie.
Erlang VM will automatically create a random cookie file when the RabbitMQ server starts up. The easiest way to proceed is to allow one node to create the file, and then copy it to all the other nodes in the cluster.
On Unix systems, the cookie will be typically located in /var/lib/rabbitmq/.erlang.cookie or $HOME/.erlang.cookie.
On Windows, the locations are C:\Users\Current User.erlang.cookie (%HOMEDRIVE% + %HOMEPATH%.erlang.cookie) or C:\Documents and Settings\Current User.erlang.cookie, and C:\Windows.erlang.cookie for RabbitMQ Windows service. If Windows service is used, the cookie should be placed in both places.
As an alternative, you can insert the option “-setcookie cookie” in the erl call in the rabbitmq-server and rabbitmqctl scripts.
When the cookie is misconfigured (for example, not identical), RabbitMQ will log errors such as “Connection attempt from disallowed node” and “Could not auto-cluster”.
上面你也看见啦 文件位置 located in /var/lib/rabbitmq/.erlang.cookie or $HOME/.erlang.cookie.
动手赶紧的,还想什么:
[root@centOSFrist ~]# cat /var/lib/rabbitmq/.erlang.cookie
ETIWQKRUVYEQMLJHASQJ
然后复制到其他节点主机当中。
[root@centOSFrist ~]# cat /var/lib/rabbitmq/.erlang.cookie
ETIWQKRUVYEQMLJHASQJ
[root@centOSSecond ~]# cat /var/lib/rabbitmq/.erlang.cookie
ETIWQKRUVYEQMLJHASQJ
[root@centOSThird ~]# cat /var/lib/rabbitmq/.erlang.cookie
ETIWQKRUVYEQMLJHASQJ
然后启动节点,记住之前先把nodename 改一下。 我就该成了 ra@centOSFirst rb@centOSSecond rc@centOSThird
然后启动一点节点,然后停止rabbitMQ应用,这里要记住启动节点的时候会启动一个erlang节点,而rabbitMQ是运作在erlang之上的应用。
[root@centOSFrist ~]# service rabbitmq-server start
Starting rabbitmq-server (via systemctl): [ 确定 ]
[root@centOSFrist ~]#
[root@centOSSecond ~]# service rabbitmq-server start
Starting rabbitmq-server (via systemctl): [ 确定 ]
[root@centOSSecond ~]#
[root@centOSThird ~]# service rabbitmq-server start
Starting rabbitmq-server (via systemctl): [ 确定 ]
[root@centOSThird ~]#
接下来先要把 rb rc 的rabbitMQ 应用停下来,然后通过rabbitmqctl 加入到ra的cluster当中。
[root@centOSSecond ~]# rabbitmqctl stop_app
Stopping node rb@centOSSecond ...
[root@centOSThird ~]# rabbitmqctl stop_app
Stopping node rc@centOSThird ...
后面的命令当中 记得看清楚主机名来操作啊。
然后就重置一下rabbitMQ里面的元数据。这个很关键。
[root@centOSSecond ~]# rabbitmqctl -n rb@centOSSecond reset
Resetting node rb@centOSSecond ...
[root@centOSThird ~]# rabbitmqctl -n rc@centOSThird reset
Resetting node rc@centOSThird ...
清空之后就开始,启动rabbitMQ应用并加入到ra@centOSFirst当中。注意:当我输入rabbitMQ in action 提供的加入群集命令时 发现提示命令未定义,可能应该是版本问题吧,我在官网上查了一下也没有这个命令我也贴出来 可能有其他版本可以用吧!
[root@centOSSecond ~]# rabbitmqctl -n rb@centOSSecond cluster ra@centOSFirst\rb@centOSSecond
//但是在我目前使用的rabbitMQ中无法使用。
//-n 之后代表节点, cluster 后面需要指定 磁盘节点。
然而我只能够参考官网的指南了,加入cluster。
[root@centOSSecond ~]# rabbitmqctl -n rb@centOSSecond join_cluster ra@centOSFirst Clustering node rb@centOSSecond with ra@centOSFirst ... Error: unable to connect to nodes [ra@centOSFirst]: nodedown DIAGNOSTICS ===========
attempted to contact: [ra@centOSFirst]
ra@centOSFirst:
* unable to connect to epmd (port 4369) on centOSFirst: nxdomain (non-existing domain)
current node details:
- node name: 'rabbitmq-cli-12@localhost'
- home dir: /var/lib/rabbitmq
- cookie hash: DZZ/rHepoZkvbV8+9fFlgw==
然而,我是猪吗?hosts都不记得改了…赶紧改。
[root@centOSFrist ~]# vim /etc/hosts
//添加如下两行
192.168.0.24 centOSSecond
192.168.0.25 centOSThird
[root@centOSSecond ~]# vim /etc/hosts
//添加如下两行
192.168.0.21 centOSFrist
192.168.0.25 centOSThird
[root@centOSThird ~]# vim /etc/hosts
//添加如下两行
192.168.0.21 centOSFrist
192.168.0.24 centOSSecond
//最后全部主机都重启一下网络
然后开始加入集群,由于我的主机名的first在输入的时候输入成frist所以,我只将错就错了 不要学我写错单词。
[root@centOSSecond ~]# rabbitmqctl -n rb@centOSSecond join_cluster ra@centOSFrist
Clustering node rb@centOSSecond with ra@centOSFrist ...
[root@centOSThird ~]# rabbitmqctl -n rc@centOSThird join_cluster ra@centOSFrist
Clustering node rc@centOSThird with ra@centOSFrist ...
然后查看一下cluster的状态
[root@centOSFrist ~]# rabbitmqctl cluster_status
Cluster status of node ra@centOSFrist ...
[{nodes,[{disc,[ra@centOSFrist,rb@centOSSecond,rc@centOSThird]}]},
{running_nodes,[ra@centOSFrist]},
{cluster_name,<<"ra@centOSFrist">>},
{partitions,[]},
{alarms,[{ra@centOSFrist,[]}]}]
[root@centOSSecond ~]# rabbitmqctl cluster_status
Cluster status of node rb@centOSSecond ...
[{nodes,[{disc,[ra@centOSFrist,rb@centOSSecond]}]},
{alarms,[{ra@centOSFrist,[]}]}]
[root@centOSThird ~]# rabbitmqctl cluster_status
Cluster status of node rc@centOSThird ...
[{nodes,[{disc,[ra@centOSFrist,rb@centOSSecond,rc@centOSThird]}]},
{alarms,[{ra@centOSFrist,[]}]}]
如果你想讲某个节点从集群里面移除,需要使用reset指令。注意如果移除一定要这样做否则这个节点将一直挂在那个集群当中。
[root@centOSThird ~]# rabbitmqctl stop_app
Stopping node rc@centOSThird ...
[root@centOSThird ~]# rabbitmqctl -n rc@centOSThird reset
Resetting node rc@centOSThird ...
[root@centOSThird ~]# rabbitmqctl cluster_status
Cluster status of node rc@centOSThird ...
[{nodes,[{disc,[rc@centOSThird]}]},{alarms,[]}]
上面已经显示他自己变回自己一个人的cluster了。然后看看其他节点的cluster是否已经将他移除吧!
[root@centOSFrist ~]# rabbitmqctl cluster_status
Cluster status of node ra@centOSFrist ...
[{nodes,[{disc,[ra@centOSFrist,rb@centOSSecond]}]},
{running_nodes,[ra@centOSFrist]},
{cluster_name,<<"ra@centOSFrist">>},
{partitions,[]},
{alarms,[{ra@centOSFrist,[]}]}]
然后集群就完成任务了,然后最后在说说镜像队列这个麻烦的东西吧。镜像队列是在你declare的时候定义的,同时分为主拷贝,从拷贝。主拷贝是实际工作的。就是说实际被消费的还是只有一个主拷贝,其余的从拷贝只是一个备份而已,如果主拷贝挂了,从拷贝就会顶上。由于我参考的 rabbitMQ 的代码是比较旧的所以当我跑的时候发现行不通的,然后又看了一下 rabbitMQ官网上的Highly Available的章节。
其实简单来说就是在额外的参数当中,添加镜像的模式 还有 镜像的参数就可以了。官网原文:
To cause queues to become mirrored, you should create a policy which matches them and sets policy keys ha-mode and (optionally) ha-params. The following table explains the options for these keys
就是两个参数 一个 ha-mode 还有 ha-params 。
一共有 三总 ha-mode 的key
- all : 所有节点都有镜像,这边比较简单不用解释。
- exactly : 具体需要多少个镜像。
- nodes : 指定那些节点有镜像。
然后我上代码:
/** * 创建了一个队列, 名称为 QUEUE_A 非持久化 非独有的 */
Map<String,Object> params = new HashMap<String,Object>();
params.put("ha-mode ","all");
this.channel.queueDeclare("tony-QUEUE",false,false,false,params);
然后再贴出一下官网的链接:
http://www.rabbitmq.com/ha.html
收工~~~~