标签:
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有如下几种定义类型:direct(直接)、topic(主题)、headers(标题)和fanout,可以通过命令 rabbitmqctl list_exchanges查看
以下为常用的三种类型:direct、topic、headers.
任何发送到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的消息都会被转发到与该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的消息都会被转发到所有关心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://www.cnblogs.com/200911/p/4856912.html