rabbitmq集群搭建

多机集群搭建
1.安装单机版的
注意:不一样于单机多节点的状况,在多机环境,若是要在cluster集群内部署多个节点,须要注意两个方面:
   1)保证须要部署的这几个节点在同一个局域网内
   2)须要有相同的Erlang Cookie,不然不能进行通讯,为保证cookie的彻底一致,采用从一个节点copy的方式,下面就会使用这种方式java


2.要搭建集群,先将以前单机版中历史记录干掉,删除rabbitmq/var/lib/rabbitmq/mnesia下的全部内容。node


3.分别在192.168.1.103   192.168.1.104  192.168.1.105节点上安装rabbitmq server。浏览器


4.在浏览器访问每个rabbitmq实例,是够能够显示登陆页面,若是显示成功,继续往下进行。服务器


5.设置不一样节点间同一认证的Erlang Cookie 
将192.168.1.103上的rabbitmq/var/lib/rabbitmq/.erlang.cookie中的内容复制到192.168.1.104和192.168.1.105上的rabbitmq/var/lib/rabbitmq/.erlang.cookie文件中, 即三台服务器必须具备相同的cookie,若是不相同的话,没法搭建集群
注意:
官方在介绍集群的文档中提到过.erlang.cookie通常会存在这两个地址:第一个是$home/.erlang.cookie也就是/root 目录下,第二个地方就是/var/lib/rabbitmq/.erlang.cookie。
若是咱们使用解压缩方式安装部署的rabbitmq,那么这个文件会在${home}目录下,也就是$home/.erlang.cookie。
若是咱们使用rpm等安装包方式进行安装的,那么这个文件会在/var/lib/rabbitmq目录下。cookie


6.分别在三个节点的/etc/hosts下设置相同的配置信息,而后重启机器
192.168.1.103 rabbit1
192.168.1.104 rabbit2
192.168.1.105 rabbit3
重启以后[root@localhost ~]#  改成[root@rabbit1 ~]# hostname就会生效app

7.使用 -detached运行各节点
rabbitmq-server -detached测试


8.建立集群
        1)rabbit1为主节点,另外两个为从节点搭建,主节点不用动,只在两个从节点运行以下命令,我这里只举一个节点(rabbit2)的例子,rabbit3执行相同的命令
         [root@rabbit2 rabbitmq]# rabbitmqctl stop_app
         Stopping rabbit application on node rabbit@rabbit2 ...
         [root@rabbit2 rabbitmq]# rabbitmqctl reset
         Resetting node rabbit@rabbit2 ...
         [root@rabbit2 rabbitmq]# rabbitmqctl join_cluster rabbit@rabbit1
         Clustering node rabbit@rabbit2 with rabbit@rabbit1 ...
         [root@rabbit2 rabbitmq]# rabbitmqctl start_app
         Starting node rabbit@rabbit2 ....net


         2)使用rabbitmqctl cluster_status查看集群状态
         [root@rabbit2 rabbitmq]# rabbitmqctl cluster_status
         Cluster status of node rabbit@rabbit2 ...
         [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
         {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]},
         {cluster_name,<<"rabbit@rabbit2">>},
         {partitions,[]},
         {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit2,[]}]}]code

9.我这里建立完成以后,以前的admin用户没法使用了,从新添加用户,参考以前搭建单机版的命令server


10.使用刚才的帐号密码登陆,出现如下界面,表示成功。

   
11.测试,生产者使用192.168.1.103:5672生产消息,消费者使用192.168.1.104:5672获取消息,若是能获取到表示集群搭建成功
Producer类:

package com.rabbitmq.test.T_helloworld;
 
 
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.test.util.ConnectionUtil;
 
 
/**
 * helloworld
 * @author lenovo
 *
 */
public class Producer {
 
 
    private final static String QUEUE_NAME = "test_queue";
 
 
    public static void main(String[] argv) throws Exception {
        //定义一个连接工厂
        ConnectionFactory factory=new ConnectionFactory();            
        //设置服务地址,IP,端口,帐号密码信息
        factory.setHost("192.168.1.103");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        //vhost:虚拟主机,一个broker里能够开设多个vhost,用做不一样用户的权限分离。
        //factory.setVirtualHost("/testrabbit");
        // 获取到链接以及mq通道
        Connection connection = factory.newConnection();
        
        //Connection connection = ConnectionUtil.getConnection();
        // 从链接中建立通道
        Channel channel = connection.createChannel();
 
 
        /*
         * 声明(建立)队列
         * 参数1:队列名称
         * 参数2:为true时server重启队列不会消失
         * 参数3:队列是不是独占的,若是为true只能被一个connection使用,其余链接创建时会抛出异常
         * 参数4:队列再也不使用时是否自动删除(没有链接,而且没有未处理的消息)
         * 参数5:创建队列时的其余参数
         */
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
 
 
        // 消息内容
        String message = "Hello World!";
        /*
         * 向server发布一条消息
         * 参数1:exchange名字,若为空则使用默认的exchange
         * 参数2:routing key
         * 参数3:其余的属性
         * 参数4:消息体
         * RabbitMQ默认有一个exchange,叫default exchange,它用一个空字符串表示,它是direct exchange类型,
         * 任何发往这个exchange的消息都会被路由到routing key的名字对应的队列上,若是没有对应的队列,则消息会被丢弃
         */
        channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
        System.out.println(" [生产者] Sent '" + message + "'");
 
 
        //关闭通道和链接
        channel.close();
        connection.close();
    }
}


Consumer类:
 

package com.rabbitmq.test.T_helloworld;
 
 
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.QueueingConsumer;
import com.rabbitmq.test.util.ConnectionUtil;
 
 
public class Consumer {
 
 
    private final static String QUEUE_NAME = "test_queue";
 
 
    public static void main(String[] argv) throws Exception {
 
 
        //定义一个连接工厂
        ConnectionFactory factory=new ConnectionFactory();            
        //设置服务地址,IP,端口,帐号密码信息
        factory.setHost("192.168.1.104");
        factory.setPort(5672);
        factory.setUsername("admin");
        factory.setPassword("admin");
        //vhost:虚拟主机,一个broker里能够开设多个vhost,用做不一样用户的权限分离。
        //factory.setVirtualHost("/testrabbit");
        // 获取到链接以及mq通道
        Connection connection = factory.newConnection();
        // 从链接中建立通道
        Channel channel = connection.createChannel();
 
 
        // 声明队列(若是你已经明确的知道有这个队列,那么下面这句代码能够注释掉,若是不注释掉的话,也能够理解为消费者必须监听一个队列,若是没有就建立一个)
        channel.queueDeclare(QUEUE_NAME, false, false, false, null);
 
 
        // 定义队列的消费者
        QueueingConsumer consumer = new QueueingConsumer(channel);
       /*
         * 监听队列
         * 参数1:队列名称
         * 参数2:是否发送ack包,不发送ack消息会持续在服务端保存,直到收到ack。  能够经过channel.basicAck手动回复ack
         * 参数3:消费者
         */ 
        channel.basicConsume(QUEUE_NAME, true, consumer);
 
 
        // 获取消息
        while (true) {
            QueueingConsumer.Delivery delivery = consumer.nextDelivery();
            String message = new String(delivery.getBody());
            System.out.println(" [消费者] Received '" + message + "'");
        }
    }
}