码迷,mamicode.com
首页 > 其他好文 > 详细

RabbitMQ之Exchange-4

时间:2015-10-06 12:54:32      阅读:239      评论:0      收藏:0      [点我收藏+]

标签:

RabbitMQ消息模型的核心思想是生产者不会将消息直接发送给队列。生产者通常不知道消息将会被哪些消费者接收,按照刚开始里介绍的rabbitMQ中所画的,生产者不是直接将消息发送给Queue么认识会交给Exchange,所以需要定义Exchange的消息分发模型来实现消息的分发,即发布者/订阅者模式,用这种模型来实现生产者与消费者之间的解耦。

那我们之前的例子中为什么只定义了一个队列,而没有定义Exchange,起不是违背了生产者不会将消息直接发送给队列的核心思想?我们来回顾一下之前生产者发布消息时的代码:

channel.basicPublish("", queueName, MessageProperties.PERSISTENT_TEXT_PLAIN, msg.getBytes());

第一个参数是空字符串,其实这个参数就是Exchange,这里定义了一个默认的Exchange。

如果用空字符串去申明一个exchange,那么系统就会使用"amq.direct"这个exchange。我们在创建一个queue的时候,默认的都会有一个和新建queue同名的routingKey绑定到这个默认的exchange上去,所以我们之前第二个参数里我们都是写的queueName。

Exchange

关于exchange,生产者只能发送消息到一个交换组件中(Exchange),exchange是一个很简单的东西,一方面它接收来自生产者的消息,另外一方面它将把来自生产者的消息放入到队列中,exchange必须知道怎么接收一个消息,而且接收的消息应该被添加到一个特定的队列?还是多个队列中?或者接收的消息被丢弃,这个规则被exchange类型所定义。

Exchange有如下几种定义类型:direct(直接)、topic(主题)、headers(标题)和fanout,可以通过命令 rabbitmqctl list_exchanges查看

以下为常用的三种类型:direct、topic、headers.

Direct Exchange

技术分享

 

任何发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue。

1.一般情况可以使用rabbitMQ自带的Exchange:""(该Exchange的名字为空字符串,之前称其为default Exchange)。

2.这种模式下不需要将Exchange进行任何绑定(binding)操作

3.消息传递时需要一个“RouteKey”,而且要求消息与这一路由键完全匹配,可以简单的理解为要发送到的队列名字。

4.如果vhost中不存在RouteKey中指定的队列名,则该消息会被抛弃。

简单的关键代码示例:

生产者

channel.exchangeDeclare(EXCHANGE_NAME,"direct");
channel.basicPublish(EXCHANGE_NAME,"routingKey",MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); 

注释:EXCHANGE_NAME可以为空字符串""。

消费者:

channel.exchangeDeclare(EXCHANGE_NAME, "direct");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "routingKey");

Fanout Exchange

技术分享

 

任何发送到Fanout Exchange的消息都会被转发到与该Exchange绑定(Binding)的所有Queue上。

1.可以理解为路由表的模式(通过exchange把消息路由到队列中)

2.这种模式不需要RouteKey

3.这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个Queue,一个Queue可以同多个Exchange进行绑定。

4.如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。

简单的关键代码示例:

生产者:

//fanout表示消息将以广播的形式分发给多个消费者

channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
channel.basicPublish(EXCHANGE_NAME,"",MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes()); 

 

消费者:

channel.exchangeDeclare(EXCHANGE_NAME, "fanout");
String queueName = channel.queueDeclare().getQueue();
channel.queueBind(queueName, EXCHANGE_NAME, "");

Topic Exchange

技术分享

任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定主题的队列(Queue)上

1.这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一个“标题”(RouteKey),Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的队列。

2.这种模式需要RouteKey,也许要提前绑定Exchange与Queue。

3.在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心所有涉及log的消息。

4.“#”表示0个或若干个关键字,“*”表示一个关键字。如“log.*”能与“log.warn”匹配,无法与“log.warn.timeout”匹配;但是“log.#”能与上述两者匹配。

5.如果Exchange没有发现能够与RouteKey匹配的Queue,则会抛弃此消息。

 

简单的关键代码示例:

生产者:

channel.exchangeDeclare(EXCHANGE_NAME,"topic");
String[] keys ={"USA.weather.1","China.weather.1","USA.people.1","China.people.1"};
for(String key:keys){
  String msg = key+":消息";
  channel.basicPublish(EXCHANGE_NAME,key,null,msg.getBytes())
}

消费者:

channel.exchangeDeclare(EXCHANGE_NAME, "topic");
String queue = channel.queueDeclare().getQueue();
String key ="*.weather.*";
channel.queueBind(queue, EXCHANGE_NAME, key);

 

 

 

RabbitMQ之Exchange-4

标签:

原文地址:http://www.cnblogs.com/200911/p/4856912.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!