RabbitMQ搭建及Spring+RabbitMQ

因为公司业务需要,负责搭建rabbitMQ集群,以及代码集成。今天分享一下RabbitMQ

RabbitMQ是流行的开源消息队列系统,用erlang语言开发。RabbitMQ是AMQP(高级消息队列协议)的标准实现。如果不熟悉AMQP,直接看RabbitMQ的文档会比较困难。不过它也只有几个关键概念,这里简单介绍。
几个概念说明:
Broker:简单来说就是消息队列服务器实体。
  Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
  Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
  Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
  Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
  vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
  producer:消息生产者,就是投递消息的程序。
  consumer:消息消费者,就是接受消息的程序。
  channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
消息队列的使用过程大概如下:
(1)客户端连接到消息队列服务器,打开一个channel。
  (2)客户端声明一个exchange,并设置相关属性。
  (3)客户端声明一个queue,并设置相关属性。
  (4)客户端使用routing key,在exchange和queue之间建立好绑定关系。
  (5)客户端投递消息到exchange。
exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里。
exchange也有几个类型,完全根据key进行投递的叫做Direct交换机,例如,绑定时设置了routing key为”abc”,那么客户端提交的消息,只有设置了key为”abc”的才会投递到队列。对key进行模式匹配后进行投递的叫做Topic交换机,符号”#”匹配一个或多个词,符号”*”匹配正好一个词。例如”abc.#”匹配”abc.def.ghi”,”abc.*”只匹配”abc.def”。还有一种不需要key的,叫做Fanout交换机,它采取广播模式,一个消息进来时,投递到与该交换机绑定的所有队列。
RabbitMQ支持消息的持久化,也就是数据写在磁盘上,为了数据安全考虑,我想大多数用户都会选择持久化。消息队列持久化包括3个部分:
  (1)exchange持久化,在声明时指定durable => 1
  (2)queue持久化,在声明时指定durable => 1
  (3)消息持久化,在投递时指定delivery_mode => 2(1是非持久化)
如果exchange和queue都是持久化的,那么它们之间的binding也是持久化的。如果exchange和queue两者之间有一个持久化,一个非持久化,就不允许建立绑定。
部署:
1、环

          基于centos7Linux系统下安装。

          Erlang1.8.1版本

          RabbitMQ3.6.3版本

2、搭建单机环境

          1、   安装erlang语言环境

                Rpm Uvhhttp://www.rabbitmq.com/releases/erlang/erlang-18.1-1.el7.centos.x86_64.rp

     Wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.3/rabbitmq-server-generic-  unix-3.6.3.tar.xz

          Xz –d rabbitmq-server-generic-unix-3.6.3.tar.xz

          Tar –xvf rabbitmq-server-generic-unix-3.6.3.tar

          cd ./rabbitmq_server-3.6.3

3、搭建集群环境(考虑到服务器限制,集群拟定三个节点)

          3、设置三台服务器并修改名称

          XXX.XX.X.XXX node1

          XXX.XX.X.XXX node2

          XXX.XX.X.XXX node3

2、<!--[endif]-->加入集群三个节点的对应关系:

          172.16.7.117 node1

          172.16.7.132 node2

3、<!--[endif]-->安装erlang语言环境

Rpm Uvhhttp://www.rabbitmq.com/releases/erlang/erlang-18.1-1.el7.centos.x86_64.rpm

RabbitMQ节点之间和命令行工具(e.g.rabbitmqctl)是使用Cookie互通的,Cookie是一组随机的数字+字母的字符串。当rabbitmq服务器启动的时候,erlangVM会自动创建一个随机内容的Cookie文件。如果是通过源安装rabbitmq的话,erlang cookie文件在/var/lib/rabbitmq/.erlang.cookie。如果是通过源码安装的rabbitmq的话,erlang cookie文件在$HOME/.erlang.cookie

由于这个文件权限是400,所以需要修改node2、node3中该文件权限为777:

            Chmod 777 .erlang.cookie

然后将文件复制到node2、node3上面

Node2:

            Chmod 777 .erlang.cookie

            Scp –r node1:/.erlang.cookie ~/

Node3:

Chmod 777 .erlang.cookie

            Scp –r node1:/.erlang.cookie ~/

分别在node1、node2、node3将权限恢复过来:

            Chmod 400 .erlang.cookie

 

5、下载rabbitMQ3.6.3

Wget http://www.rabbitmq.com/releases/rabbitmq-server/v3.6.3/rabbitmq-server-generic-unix-3.6.3.tar.xz

Xz –d rabbitmq-server-generic-unix-3.6.3.tar.xz

Tar –xvf rabbitmq-server-generic-unix-3.6.3.tar

cd ./rabbitmq_server-3.6.3

cd sbin/

启用web管理界面

./rabbitmq-plugins enable rabbitmq_management

使用detached参数,在后台启动rabbit node

要先停止现有的rabbitmq-server 在重新再后台运行

./rabbitmqctl stop

./rabbitmq-server –detached

通过rabbitmqctl cluster_status命令,可以查看节点的状态

将node1、node2、node3组成集群

因为rabbitmq-server启动时,会一起启动节点和应用,它预先设置rabbitmq应用为standalone模式。要将一个节点加入到现有的集群中,需要停止这个应用并将节点设置为原始状态,然后就为加入集群准备好了。如果使用./rabbitmqctl stop,应用和节点都将被关闭。所以使用rabbitmqctl stop_app仅仅关闭应用。

     Rabbitmqctl stop_app

     Rabbitmqctl join_cluster rabbit@node1

     Rabbitmqctl start_app

     使用内存节点

     Rabbitmqctl join_cluster --ram rabbit@node1

 

RabbitMQ镜像功能

在任意一个节点之下下面命令

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

将所有队列设置为镜像队列,即队列会被复制到各个节点,各个节点状态保持一致。<!--EndFragment-->

cd sbin/

启用web管理界面

./rabbitmq-plugins enable rabbitmq_management

启动

./rabbitmq-server start

因为rabbitmq默认账户guest不等在远程登录所以需要创建用户。

./rabbitmqctl add_user admin admin  前一个admin为账户,后一个admin为密码

设置权限

./rabbitmqctl set_user_tags admin administrator

访问ip:15672

 

Spring集成rabbitMQ

Maven依赖

    

     <dependency>  
	            <groupId>org.springframework.amqp</groupId>  
	            <artifactId>spring-rabbit</artifactId>  
	            <version>1.3.5.RELEASE</version>  
        </dependency>

 

Spring配置文件application.xml
	<?xml version="1.0" encoding="UTF-8"?>  
	<beans xmlns="http://www.springframework.org/schema/beans"  
	       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"  
	       xmlns:p="http://www.springframework.org/schema/p"  
	       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd  
	    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">  
	  
	  
	    <import resource="classpath*:rabbitMq.xml" />  
	  
	  
	    <!-- 扫描指定package下所有带有如@controller,@services,@resource,@ods并把所注释的注册为Spring Beans -->  
	    <context:component-scan base-package="com.xin.consumer,com.xin.producer" />  
	  
	  
	    <!-- 激活annotation功能 -->  
	    <context:annotation-config />  
	    <!-- 激活annotation功能 -->  
	    <context:spring-configured />  
	  
</beans>
 
RabbitMQ配置文件:RabbitMQ.xml
1.	<?xml version="1.0" encoding="UTF-8"?>  
2.	<beans xmlns="http://www.springframework.org/schema/beans"  
3.	       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"  
4.	       xsi:schemaLocation="http://www.springframework.org/schema/beans  
5.	     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
6.	     http://www.springframework.org/schema/beans  
7.	     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd  
8.	     http://www.springframework.org/schema/rabbit  
9.	     http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd">  
10.	    <!--配置connection-factory,指定连接rabbit server参数 -->  
11.	    <rabbit:connection-factory id="connectionFactory"  
12.	                               username="guest" password="guest" host="localhost" port="5672" />  
13.	  
14.	  
15.	    <!--direct 一对一传输-->  
16.	    <!--定义rabbit template用于数据的接收和发送 -->  
17.	    <rabbit:template id="amqpTemplate"  connection-factory="connectionFactory"  
18.	                     exchange="exchangeTest" />  
19.	  
20.	    <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 -->  
21.	    <rabbit:admin connection-factory="connectionFactory" />  
22.	  
23.	    <!--定义queue -->  
24.	    <rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" />  
25.	  
26.	    <!-- 定义direct exchange,绑定queueTest -->  
27.	    <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false">  
28.	        <rabbit:bindings>  
29.	            <rabbit:binding queue="queueTest" key="queueTestKey"></rabbit:binding>  
30.	        </rabbit:bindings>  
31.	    </rabbit:direct-exchange>  
32.	  
33.	  
34.	    <!-- 消息接收者 -->  
35.	    <bean id="messageReceiver" class="com.xin.consumer.MessageConsumer"></bean>  
36.	  
37.	    <!-- queue litener  观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象-->  
38.	    <rabbit:listener-container connection-factory="connectionFactory">  
39.	        <rabbit:listener queues="queueTest" ref="messageReceiver"/>  
40.	    </rabbit:listener-container>  
41.	  
42.	  
43.	  
44.	  
45.	  
46.	  
47.	  
48.	  
49.	  
50.	  
51.	  
52.	    <!--topic 匹配传输-->  
53.	    <rabbit:template id="topicTemplate"  connection-factory="connectionFactory"  
54.	                     exchange="topicExchange"/>  
55.	  
56.	    <!--定义queue -->  
57.	    <rabbit:queue name="topicQueue" durable="true" auto-delete="false" exclusive="false" />  
58.	  
59.	    <!--topic交换器 pattern与topicTemplate.convertAndSend("foo.bar",message);第一个参数匹配-->  
60.	    <rabbit:topic-exchange name="topicExchange">  
61.	        <rabbit:bindings>  
62.	            <rabbit:binding queue="topicQueue" pattern="info.*" />  
63.	        </rabbit:bindings>  
64.	    </rabbit:topic-exchange>  
65.	  
66.	    <rabbit:listener-container connection-factory="connectionFactory">  
67.	        <rabbit:listener ref="topic1" queues="topicQueue"/>  
68.	    </rabbit:listener-container>  
69.	  
70.	    <bean id="topic1" class="com.xin.consumer.TopicConsumer"/>  
71.	  
72.	  
73.	  
74.	  
75.	  
76.	  
77.	  
78.	  
79.	    <!--fanout 把一条消息通过多条队列传输出去-->  
80.	  
81.	    <rabbit:template id="fanoutTemplate"  connection-factory="connectionFactory"  
82.	                     exchange="fanoutExchange"/>  
83.	  
84.	    <!--定义queue -->  
85.	    <rabbit:queue name="fanoutQueue" durable="true" auto-delete="false" exclusive="false" />  
86.	    <rabbit:queue name="fanoutQueue2" durable="true" auto-delete="false" exclusive="false" />  
87.	  
88.	    <!--topic交换器-->  
89.	    <rabbit:fanout-exchange name="fanoutExchange">  
90.	        <rabbit:bindings>  
91.	            <rabbit:binding queue="fanoutQueue"></rabbit:binding>  
92.	            <rabbit:binding queue="fanoutQueue2"></rabbit:binding>  
93.	        </rabbit:bindings>  
94.	    </rabbit:fanout-exchange>  
95.	  
96.	    <rabbit:listener-container connection-factory="connectionFactory">  
97.	        <rabbit:listener ref="fanoutConsumer" queues="fanoutQueue"/>  
98.	        <rabbit:listener ref="fanoutConsumer2" method="foo" queues="fanoutQueue2"/>  
99.	    </rabbit:listener-container>  
  
	    <bean id="fanoutConsumer" class="com.xin.consumer.FanoutConsumer"/>  
    <bean id="fanoutConsumer2" class="com.xin.consumer.FanoutConsumer2"/>  
	  
</beans>

 

实现direct交换机传输
1.	package com.xin.producer;  
2.	  
3.	import org.slf4j.Logger;  
4.	import org.slf4j.LoggerFactory;  
5.	import org.springframework.amqp.core.AmqpTemplate;  
6.	import org.springframework.stereotype.Service;  
7.	  
8.	import javax.annotation.Resource;  
9.	  
10.	/** 
11.	 * Created by wuye on wuye on 2016/10/5 19:57 
12.	 * 
13.	 * @Description 
14.	 */  
15.	@Service  
16.	public class MessageProducer {  
17.	  
18.	    private Logger logger = LoggerFactory.getLogger(MessageProducer.class);  
19.	  
20.	    @Resource  
21.	    private AmqpTemplate amqpTemplate;  
22.	  
23.	    public void sendMessage(Object message){  
24.	        logger.info("to send message:{}",message);  
25.	        amqpTemplate.convertAndSend("queueTestKey",message);  
26.	    }  
27.	}  
消费端:MessageConsumer
1.		package com.xin.consumer;  
2.	  
3.	import com.xin.producer.MessageProducer;  
4.	import org.slf4j.Logger;  
5.	import org.slf4j.LoggerFactory;  
6.	import org.springframework.amqp.core.Message;  
7.	import org.springframework.amqp.core.MessageListener;  
8.	import org.springframework.context.support.AbstractApplicationContext;  
9.	import org.springframework.context.support.ClassPathXmlApplicationContext;  
10.	  
11.	/** 
12.	 * Created by wuye on wuye on 2016/10/5 19:57 
13.	 * 
14.	 * @Description 消费接收 
15.	 */  
16.	public class MessageConsumer implements MessageListener {  
17.	  
18.	    private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);  
19.	  
20.	    @Override  
21.	    public void onMessage(Message message) {  
22.	        logger.info("receive message:{}",message);  
23.	        System.out.println(new String(message.getBody()));  
24.	    }  
25.	  
26.	    public static void main(final String... args) throws Exception {  
27.	        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");  
28.	        MessageProducer messageProducer = (MessageProducer) ctx.getBean("messageProducer");  
29.	        messageProducer.sendMessage("-------------hello,3453465465467456456456^^^^^^66666!");  
30.	        Thread.sleep(1000);  
31.	        ctx.destroy();  
32.	    }  
33.	  
} 
 
消费端:MessageConsumer
1.		package com.xin.consumer;  
2.	  
3.	import com.xin.producer.MessageProducer;  
4.	import org.slf4j.Logger;  
5.	import org.slf4j.LoggerFactory;  
6.	import org.springframework.amqp.core.Message;  
7.	import org.springframework.amqp.core.MessageListener;  
8.	import org.springframework.context.support.AbstractApplicationContext;  
9.	import org.springframework.context.support.ClassPathXmlApplicationContext;  
10.	  
11.	/** 
12.	 * Created by wuye on 2016/10/5 19:57 
13.	 * 
14.	 * @Description 消费接收 
15.	 */  
16.	public class MessageConsumer implements MessageListener {  
17.	  
18.	    private Logger logger = LoggerFactory.getLogger(MessageConsumer.class);  
19.	  
20.	    @Override  
21.	    public void onMessage(Message message) {  
22.	        logger.info("receive message:{}",message);  
23.	        System.out.println(new String(message.getBody()));  
24.	    }  
25.	  
26.	    public static void main(final String... args) throws Exception {  
27.	        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("application.xml");  
28.	        MessageProducer messageProducer = (MessageProducer) ctx.getBean("messageProducer");  
29.	        messageProducer.sendMessage("-------------hello,xin3453465465467456456456^^^^^^66666!");  
30.	        Thread.sleep(1000);  
31.	        ctx.destroy();  
32.	    }  
33.	  
}  
 
<!--EndFragment-->

猜你喜欢

转载自wuye112.iteye.com/blog/2370077