RabbitMQ
来源:互联网 发布:云服务器搭建sql serv 编辑:程序博客网 时间:2024/05/01 14:08
一、rabbitMQ简介
1. 1、rabbitMQ的优点(适用范围)
- 基于erlang语言开发具有高可用高并发的优点,适合集群服务器。
- 健壮、稳定、易用、跨平台、支持多种语言、文档齐全。
- 有消息确认机制和持久化机制,可靠性高。
- 开源
- 其他MQ的优势:
- Apache ActiveMQ曝光率最高,但是可能会丢消息。
- ZeroMQ延迟很低、支持灵活拓扑,但是不支持消息持久化和崩溃恢复。
1.2、几个概念说明
- producer&Consumer
producer指的是消息生产者,consumer消息的消费者。 Queue
消息队列,提供了FIFO的处理机制,具有缓存消息的能力。rabbitmq中,队列消息可以设置为持久化,临时或者自动删除。
设置为持久化的队列,queue中的消息会在server本地硬盘存储一份,防止系统crash,数据丢失
设置为临时队列,queue中的数据在系统重启之后就会丢失
设置为自动删除的队列,当不存在用户连接到server,队列中的数据会被自动删除ExchangeExchange类似于数据通信网络中的交换机,提供消息路由策略。rabbitmq中,producer不是通过信道直接将消息发送给queue,而是先发送给Exchange。一个Exchange可以和多个Queue进行绑定,producer在传递消息的时候,会传递一个ROUTING_KEY,Exchange会根据这个ROUTING_KEY按照特定的路由算法,将消息路由给指定的queue。和Queue一样,Exchange也可设置为持久化,临时或者自动删除。
Exchange有4种类型:direct(默认),fanout, topic, 和headers,不同类型的Exchange转发消息的策略有所区别:
- Direct
直接交换器,工作方式类似于单播,Exchange会将消息发送完全匹配ROUTING_KEY的Queue - fanout
广播是式交换器,不管消息的ROUTING_KEY设置为什么,Exchange都会将消息转发给所有绑定的Queue。 - topic
主题交换器,工作方式类似于组播,Exchange会将消息转发和ROUTING_KEY匹配模式相同的所有队列,比如,ROUTING_KEY为user.stock的message会转发给绑定匹配模式为 * .stock,user.stock, * . * 和#.user.stock.#的队列。( * 表是匹配一个任意词组,#表示匹配0个或多个词组) - headers
消息体的header匹配(ignore)
- Direct
Binding
所谓绑定就是将一个特定的 Exchange 和一个特定的 Queue 绑定起来。Exchange 和Queue的绑定可以是多对多的关系。- virtual host
在rabbitmq server上可以创建多个虚拟的message broker,又叫做virtual hosts (vhosts)。每一个vhost本质上是一个mini-rabbitmq server,分别管理各自的exchange,和bindings。vhost相当于物理的server,可以为不同app提供边界隔离,使得应用安全的运行在不同的vhost实例上,相互之间不会干扰。producer和consumer连接rabbit server需要指定一个vhost。
1.3、消息队列的使用过程
- 客户端连接到消息队列服务器,打开一个channel。
- 客户端声明一个exchange,并设置相关属性。
- 客户端声明一个queue,并设置相关属性。
- 客户端使用routing key,在exchange和queue之间建立好绑定关系。
- 客户端投递消息到exchange。
- exchange接收到消息后,就根据消息的key和已经设置的binding,进行消息路由,将消息投递到一个或多个队列里
二、CentOS 安装RabbitMq
安装erlang(版本:otp_src_17.1.tar.gz)
默认安装目录/opt/下 :将准备好的otp_src_17.1.tar.gz放在/opt/
[root@iZ235pdz8oaZ opt]# ll
-rw-r–r– 1 root root 28182213 Feb 24 15:44 otp_sr_17.1.tar.gz
drwxr-xr-x. 2 root root 4096 Nov 22 2013 rh解压otp_src_17.1.tar.gz
[root@iZ235pdz8oaZ opt]# tar xzvf otp_src_17.1.tar.gz
[root@iZ235pdz8oaZ opt]# ll
drwxr-xr-x. 11 2011 uucp 4096 6月 24 2014 otp_src_17.1
-rw-r–r–. 1 root root 66912681 3月 15 06:26 otp_src_17.1.tar.gz
-rw-r–r–. 1 root root 4106510 3月 15 06:27 rabbitmq-server-3.3.5-1.noarch.rpm然后:
[root@iZ235pdz8oaZ opt]# cd otp_src_17.1
[root@iZ235pdz8oaZ otp_src_17.1]# ./configure没问题,再继续
[root@iZ235pdz8oaZ otp_src_17.1]# make
[root@iZ235pdz8oaZ otp_src_17.1]# make install
1.2. 安装RabbitMQ(版本:rabbitmq-server-3.3.5-1)
默认安装目录/opt/下 :将准备好的rabbitmq-server-3.3.5-1.noarch.rpm放在/opt/
[root@iZ235pdz8oaZ opt]# ll
drwxrwxrwx. 11 2011 uucp 4096 3月 15 07:22 otp_src_17.1
-rw-r–r–. 1 root root 66912681 3月 15 06:26 otp_src_17.1.tar.gz
-rw-r–r–. 1 root root 4106510 3月 15 06:27 rabbitmq-server-3.3.5-1.noarch.rpm强制安装rabbitmq-server-3.3.5-1.noarch.rpm
[root@iZ235pdz8oaZ opt]#
rpm -i –force –nodeps rabbitmq-server-3.3.5-1.noarch.rpm- 开启插件rabbitmq_management
[root@iZ235pdz8oaZ opt]# rabbitmq-plugins enable rabbitmq_management - 创建用户
[root@iZ235pdz8oaZ opt]# rabbitmqctl add_user ddd ddd - 配置用户权限
[root@iZ235pdz8oaZ opt]# rabbitmqctl set_user_tags ddd administrator
安装了插件以后可以通过http://192.168.2.175:15672/#/查看
三、简单Java实例
首先是消息生产者和提供者的基类
package com.kxtx.padserver.common.rabbit;import java.io.IOException;import com.rabbitmq.client.Channel;import com.rabbitmq.client.Connection;import com.rabbitmq.client.ConnectionFactory;/** * * 功能概要: EndPoint类型的队列 * * @author linbingwen * @since 2016年1月11日 */public abstract class RabbitMQBase{ protected Channel channel; protected Connection connection; protected String endPointName; public RabbitMQBase(String endpointName) throws IOException{ this.endPointName = endpointName; //Create a connection factory ConnectionFactory factory = new ConnectionFactory(); //hostname of your rabbitmq server factory.setHost("192.168.2.175"); factory.setPort(5672); factory.setUsername("ddd"); factory.setPassword("ddd"); //getting a connection connection = factory.newConnection(); //creating a channel channel = connection.createChannel(); //declaring a queue for this channel. If queue does not exist, //it will be created on the server. channel.queueDeclare(endpointName, false, false, false, null); } /** * 关闭channel和connection。并非必须,因为隐含是自动调用的。 * @throws IOException */ public void close() throws IOException{ this.channel.close(); this.connection.close(); }}
消息提供者
package com.kxtx.padserver.common.rabbit; import java.io.IOException;import java.io.Serializable;import org.apache.commons.lang.SerializationUtils;/** * * 功能概要:消息生产者 * * @author linbingwen * @since 2016年1月11日 */public class Producer extends RabbitMQBase{ public Producer(String endPointName) throws IOException{ super(endPointName); } public void sendMessage(Serializable object) throws IOException { channel.basicPublish("",endPointName, null, SerializationUtils.serialize(object)); } }
消息消费者
package com.kxtx.padserver.common.rabbit;import java.io.IOException;import java.util.HashMap;import java.util.Map;import org.apache.commons.lang.SerializationUtils;import com.rabbitmq.client.AMQP.BasicProperties;import com.rabbitmq.client.Consumer;import com.rabbitmq.client.Envelope;import com.rabbitmq.client.ShutdownSignalException;/** * * 功能概要:读取队列的程序端,实现了Runnable接口 * * @author linbingwen * @since 2016年1月11日 */public class QueueConsumer extends RabbitMQBase implements Runnable, Consumer{ public QueueConsumer(String endPointName) throws IOException{ super(endPointName); } public void run() { try { //start consuming messages. Auto acknowledge messages. channel.basicConsume(endPointName, true,this); } catch (IOException e) { e.printStackTrace(); } } /** * Called when consumer is registered. */ public void handleConsumeOk(String consumerTag) { System.out.println("Consumer "+consumerTag +" registered"); } /** * Called when new message is available. */ public void handleDelivery(String consumerTag, Envelope env, BasicProperties props, byte[] body) throws IOException { Map map = (HashMap)SerializationUtils.deserialize(body); System.out.println("Message Number "+ map.get("message number") + " received."); } public void handleCancel(String consumerTag) {} public void handleCancelOk(String consumerTag) {} public void handleRecoverOk(String consumerTag) {} public void handleShutdownSignal(String consumerTag, ShutdownSignalException arg1) {}}
测试
package com.kxtx.padserver.common.rabbit;import java.io.IOException;import java.sql.SQLException;import java.util.HashMap;/** * * @author * @create:2016年3月28日 上午9:27:14 * @description: */public class RabbitMqTest { public RabbitMqTest() throws Exception{ QueueConsumer consumer = new QueueConsumer("queue"); Thread consumerThread = new Thread(consumer); consumerThread.start(); Producer producer = new Producer("queue"); for (int i = 0; i < 1000000; i++) { HashMap message = new HashMap(); message.put("message number", i); producer.sendMessage(message); System.out.println("Message Number "+ i +" sent."); } } /** * @param args * @throws SQLException * @throws IOException */ public static void main(String[] args) throws Exception{ new RabbitMqTest(); }}
四、Spring整合RabbitMQ
RabbitMQ配置信息 rabbitMq.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:rabbit="http://www.springframework.org/schema/rabbit" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd"> <!--配置connection-factory,指定连接rabbit server参数 --> <rabbit:connection-factory id="connectionFactory" username="ddd" password="ddd" host="192.168.2.175" port="5672" /> <!--通过指定下面的admin信息,当前producer中的exchange和queue会在rabbitmq服务器上自动生成 --> <rabbit:admin connection-factory="connectionFactory" /> <!--定义queue --> <rabbit:queue name="queueTest" durable="true" auto-delete="false" exclusive="false" /> <!-- 定义direct exchange,绑定queueTest --> <rabbit:direct-exchange name="exchangeTest" durable="true" auto-delete="false"> <rabbit:bindings> <rabbit:binding queue="queueTest" key="queueTestKey"></rabbit:binding> </rabbit:bindings> </rabbit:direct-exchange> <!--定义rabbit template用于数据的接收和发送 --> <rabbit:template id="amqpTemplate" connection-factory="connectionFactory" exchange="exchangeTest" /> <!-- 消息接收者 --> <bean id="messageReceiver" class="com.kxtx.padserver.common.spring.MessageConsumer"></bean> <!-- queue litener 观察 监听模式 当有消息到达时会通知监听在对应的队列上的监听对象--> <rabbit:listener-container connection-factory="connectionFactory"> <rabbit:listener queues="queueTest" ref="messageReceiver"/> </rabbit:listener-container></beans>
Spring 配置文件
<?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.kxtx.padserver.common.spring" /> <!-- 激活annotation功能 --> <context:annotation-config /></beans>
生产者
package com.kxtx.padserver.common.spring;import javax.annotation.Resource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.amqp.core.AmqpTemplate;import org.springframework.stereotype.Service;/** * 功能概要:消息产生,提交到队列中去 * * @author linbingwen * @since 2016年1月15日 */@Servicepublic class MessageProducer { private Logger logger = LoggerFactory.getLogger(MessageProducer.class); @Resource private AmqpTemplate amqpTemplate; public void sendMessage(Object message){ logger.info("to send message:{}",message); amqpTemplate.convertAndSend("queueTestKey",message); }}
消费者
package com.kxtx.padserver.common.spring;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.amqp.core.Message;import org.springframework.amqp.core.MessageListener;/** * 功能概要:消费接收 * * @author linbingwen * @since 2016年1月15日 */public class MessageConsumer implements MessageListener { private Logger logger = LoggerFactory.getLogger(MessageConsumer.class); @Override public void onMessage(Message message) { logger.info("receive message:{}",message); System.out.println("hello world"); }}
测试
package com.kxtx.padserver.common.spring;import org.junit.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.AbstractJUnit4SpringContextTests;/** * * @author * @create:2016年3月28日 上午10:10:15 * @description: */@ContextConfiguration({ "classpath:application.xml" })public class SpringMqTest extends AbstractJUnit4SpringContextTests { @Autowired private MessageProducer messageProducer; @Test public void test(){ for(int i = 0; i < 100; i++){ messageProducer.sendMessage("hello world"); } }}
- rabbitmq
- RabbitMQ
- RabbitMQ
- RabbitMQ
- rabbitmq
- RabbitMQ
- RabbitMQ
- rabbitmq
- RabbitMQ
- rabbitmq
- RabbitMQ
- rabbitmq
- RabbitMQ
- rabbitmq
- RabbitMQ
- RabbitMQ
- RabbitMQ
- rabbitmq
- Change Yii 2.0 Default Controller
- RADASM中使用DOSBOX来运行DOS/BIOS程序(16位)
- 大数据并发问题
- mysql中的触发器
- 快速排序、堆排序、归并排序
- RabbitMQ
- 浅析Java中Map与HashMap,Hashtable,HashSet的区别
- 开始学习深度学习和循环神经网络Some starting points for deep learning and RNNs
- OpenCV--SVM多分类问题
- WaitForSingleObject函数的使用
- FMDB
- c++作业2-分段函数求值,两点距离,模拟ATM
- android 关于跳转系统设置页面
- ASP VBscript使用逻辑运算中的 and or