rabbitmq exchange模式

rabbitmq exchange

主要介绍rabbitmq常用的三种exchange模式:direct, fanout, topic.

Virtual Host

为了在一个单独的代理上实现多个隔离的环境(用户、用户组、交换机、队列 等),AMQP提供了一个虚拟主机(virtual hosts - vhosts)的概念,默认的virtual host为 “/“.

Default exchange (默认交换机)

默认交换机(default exchange)实际上是一个由消息代理预先声明好的没有名字(名字为空字符串)的直连交换机(direct exchange)。它有一个特殊的属性使得它对于简单应用特别有用处:那就是每个新建队列(queue)都会自动绑定到默认交换机上,绑定的路由键(routing key)名称与队列名称相同。

Direct Exchange

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

  • 一般情况可以使用rabbitMQ自带的Exchange:””(该Exchange的名字为空字符串,下文称其为default Exchange)。

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

  • 消息传递时需要一个“RouteKey”,可以简单的理解为要发送到的队列名字。

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

1
2
3
4
5
6
7
8
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);

Fanout Exchange

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

  • 可以理解为路由表的模式

  • 这种模式不需要RouteKey

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

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

1
2
3
4
5
6
7
8
9
10
11
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);

Topic Exchange

任何发送到Topic Exchange的消息都会被转发到所有关心RouteKey中指定话题的Queue上.

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

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

  • 在进行绑定时,要提供一个该队列关心的主题,如“#.log.#”表示该队列关心所有涉及log的消息(一个RouteKey为”MQ.log.error”的消息会被转发到该队列)。

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

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

1
2
3
4
5
6
7
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);

热评文章