RabbitMQ之Exchange

来源:互联网 发布:对付淘宝卖家的狠招 编辑:程序博客网 时间:2024/05/26 15:57

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);


之前包括本节讲到的代码示例链接:http://download.csdn.net/detail/xiaoyatouvsanan/7571743


0 0
原创粉丝点击