因为公司业务需要,负责搭建rabbitMQ集群,以及代码集成。今天分享一下RabbitMQ
Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列。
Queue:消息队列载体,每个消息都会被投入到一个或多个队列。
Binding:绑定,它的作用就是把exchange和queue按照路由规则绑定起来。
Routing Key:路由关键字,exchange根据这个关键字进行消息投递。
vhost:虚拟主机,一个broker里可以开设多个vhost,用作不同用户的权限分离。
producer:消息生产者,就是投递消息的程序。
consumer:消息消费者,就是接受消息的程序。
channel:消息通道,在客户端的每个连接里,可建立多个channel,每个channel代表一个会话任务。
(2)客户端声明一个exchange,并设置相关属性。
(3)客户端声明一个queue,并设置相关属性。
(4)客户端使用routing key,在exchange和queue之间建立好绑定关系。
(5)客户端投递消息到exchange。
(1)exchange持久化,在声明时指定durable => 1
(2)queue持久化,在声明时指定durable => 1
(3)消息持久化,在投递时指定delivery_mode => 2(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>
<?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>
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>
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. }
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. }