开源项目

知识点

相关文章

更多

最近更新

更多

RabbitMQ 三种Exchange(fanout,direct,topic)模式

2019-03-05 23:22|来源: 网路

RabbitMQ提供了四种Exchange:fanout,direct,topic,header, header模式在实际使用中较少,本文只对前三种模式进行比较。
性能排序:fanout > direct >> topic。比例大约为11:10:6


1、Fanout Exchange



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

1、可以理解为路由表的模式
2、这种模式不需要RouteKey
3、这种模式需要提前将Exchange与Queue进行绑定,一个Exchange可以绑定多个Queue,一个Queue可以同多个Exchange进行绑定。
4、一个发送到交换机的消息都会被转发到与该交换机绑定的所有队列上。很像子网广播,每台子网内的主机都获得了一份复制的消息。
5、如果接受到消息的Exchange没有与任何Queue绑定,则消息会被抛弃。
6、Fanout交换机转发消息是最快的。
Channel channel = connection.createChannel();  
channel.exchangeDeclare("exchangeName", "fanout"); //direct fanout topic  
channel.queueDeclare("queueName");  
channel.queueBind("queueName", "exchangeName", "routingKey");  
channel.queueDeclare("queueName1");  
channel.queueBind("queueName1", "exchangeName", "routingKey1");  
byte[] messageBodyBytes = "hello world".getBytes();  
//路由键需要设置为空  
channel.basicPublish("exchangeName", "", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);


2、 Direct Exchange

任何发送到Direct Exchange的消息都会被转发到RouteKey中指定的Queue。
1、处理路由键
2、需要将一个队列绑定到交换机上,要求该消息与一个特定的路由键完全匹配。这是一个完整的匹配。如果一个队列绑定到该交换机上要求路由键 “dog”,则只有被标记为“dog”的消息才被转发,不会转发dog.puppy,也不会转发dog.guard,只会转发dog。
3、一般情况可以使用rabbitMQ自带的Exchange:" "(该Exchange的名字为空字符串,下文称其为default Exchange)。
4、这种模式下不需要将Exchange进行任何绑定(binding)操作
5、消息传递时需要一个“RouteKey”,可以简单的理解为要发送到的队列名字。
6、如果vhost中不存在RouteKey中指定的队列名,则该消息会被抛弃。
Channel channel = connection.createChannel();  
channel.exchangeDeclare("exchangeName", "direct"); //direct fanout topic  
channel.queueDeclare("queueName");  
channel.queueBind("queueName", "exchangeName", "routingKey");  
byte[] messageBodyBytes = "hello world".getBytes();  
//需要绑定路由键  
channel.basicPublish("exchangeName", "routingKey", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);


3、 Topic Exchange

任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上
1、这种模式较为复杂,简单来说,就是每个队列都有其关心的主题,所有的消息都带有一个“标题”(RouteKey),Exchange会将消息转发到所有关注主题能与RouteKey模糊匹配的队列。
2、这种模式需要RouteKey,也许要提前绑定Exchange与Queue。
3、在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心所有涉及log的消息(一个RouteKey为”MQ.log.error”的消息会被转发到该队列)。
4、“#”表示0个或若干个关键字,“*”表示一个关键字。如“log.*”能与“log.warn”匹配,无法与“log.warn.timeout”匹配;但是“log.#”能与上述两者匹配。
5、同样,如果Exchange没有发现能够与RouteKey匹配的Queue,则会抛弃此消息。
Channel channel = connection.createChannel();  
channel.exchangeDeclare("exchangeName", "topic"); //direct fanout topic  
channel.queueDeclare("queueName");  
channel.queueBind("queueName", "exchangeName", "routingKey.*");  
byte[] messageBodyBytes = "hello world".getBytes();  
channel.basicPublish("exchangeName", "routingKey.one", MessageProperties.PERSISTENT_TEXT_PLAIN, messageBodyBytes);


书生整理于网络


相关问答

更多
  • 如果没有连接的消费者可以在发布消息时处理消息,则需要持久的队列来存储消息。 交换不存储消息,但队列可以。 令人困惑的部分是交易所可以被标记为“持久”,但是真正意义的是,如果您重新启动经纪人, 交易所本身将仍然存在,但并不意味着发送到该交易所的任何消息将自动持续存在。 鉴于此,有两个选择: 在您启动发布商之前自行创建队列,执行管理步骤 。 您可以使用Web UI或命令行工具来执行此操作。 确保将其创建为耐用队列,以便即使没有活动的消费者,它也会存储路由到它的消息。 假设您的消费者被编码为在启动时始终声明(并因 ...
  • Applying plugin configuration to rabbit@manish-Lenovo-G510... failed. Error: {could_not_start,rabbitmq_web_mqtt, {undef, [{lager_config,get, Lager只在3.7.0版本中,很可能是你构建了master分支。 要构建插件版本3.6.2您应该: git clone https://github.com/rabb ...
  • 您可以使用路由密钥,通过创建交换机和绑定到交换机的名为Device60的队列。 channel.queueBind("Device60","myexchange","device.60") 此时,您可以使用路由键发布消息。 例如: channel.basicPublish("myexchange","device.60",mymessage); 现在, Device60将接收消息并存储它们,直到消费者在线。 对于其他设备,它是相同的: channel.queueBind("Device50","mye ...
  • 有没有办法如何进行排除模式匹配 不。 路由键只匹配,不排除 Is there any way how to make exclude pattern matching nope. routing keys only match, not exclude
  • 不,这是不可配置的,但是也存在一个默认的扇出交换。 No, this isn't configurable, but there is a default fanout exchange that is also created.
  • 无论使用路由密钥还是绑定,扇出交换都将始终向每个绑定队列传递消息。 在扇出交换中完全忽略路由密钥。 根据您的需求描述,您所寻找的不是粉丝交换。 如果要根据所使用的路由密钥将消息传递到特定队列,则需要使用直接交换(用于路由密钥的简单匹配)或主题交换(用于复杂的路由密钥模式匹配) a fanout exchange will always deliver a message to every bound queue, no matter the routing key used or binding. the ...
  • GAE与RabbitMQ不具有可比性,因为您的问题几乎没有意义。 RabbitMQ只是消息传递,您很可能必须设置更多基础架构来支持您的用例。 GAE是一个完整的基础设施。 也就是说,RabbitMQ每秒可以处理大量的消息。 也许你想为手机游戏连接到一个API,以及一些应用程序逻辑来处理这些消息。 您不会让游戏客户端连接到您的RabbitMQ服务器并直接与其他客户端通信。 在GAE上,您通常会有请求并立即回复。 如果您需要持续时间较长的连接并允许您将消息推送到游戏客户端(不使用APN等),您可能需要考虑XMP ...
  • 每个队列也绑定到默认交换(“”),路由密钥等于队列名称。 您可以简单地将过期的死信直接路由到原始队列。 Every queue is also bound to the default exchange ("") with the routing key equal to the queue name. You can simply route your expired dead letters directly to the original queue.
  • 这可以通过直接或主题交换来完成,并且在您的交换中需要4个绑定。 假设以名为“MainEx”的交换机为例,路由键将如下设置: | exchange | binding | queue | | -------- | ---------------- | ------ | | MainEx | MainRoute.Route1 | Queue1 | | MainEx | MainRoute.Route2 | Queue2 | | MainEx | MainRoute ...
  • 我想说这是一个简化的问题 。 如果您需要的只是一个拓扑,其中每个特定的路由键以1:1的方式映射队列(同一应用程序中多个工作者之间的任务循环分布是RabbitMQ文档中引用的示例),那么直接交换可能是更易于使用和使用,以及您所需要的一切。 这并不是说你无法用Topic Exchanges完成同样的事情(你可以)。 同样,通过Fanout交换 ,如果您的情况需要简单地广播消息,您可能会发现Fanout交换更容易使用。 同样,这并不是说你无法使用Topic Exchanges完成同样的事情(你可以)。 我通常只使 ...