概要

AMQP-0-9-1中提供了queue.bind方法用于绑定一个队列到一个交换器,然后发送消息的时候,数据流总是先通过交换器(source)最终到达目标队列中(destination)。RabbitMQ实现了扩展,为交换器提供了一个exchange.bind方法用于绑定一个交换器到另一个交换器。交换器之间的绑定和队列与交换器的绑定在语义上是相同的:单向的、使用路由键和多种交换器类型。这一点允许使用者创建更丰富的路由拓扑。exchange.bind方法中的source和destination反映了消息的流向:从源(source)交换器到目标(destination)交换器。

queue.bind方法一样,可以在相同的绑定端点上创建多个不同的交换器绑定,例如:

  • exchange-source -> exchange-destination-1 -> queue-1
  • exchange-source -> exchange-destination-2 -> queue-2
  • exchange-source -> exchange-destination-3 -> queue-3

RabbitMQ在消息传递期间检测并消除循环,并确保在任何路由拓扑上传递给定路由的每个队列,每个队列将只接收该消息的一个副本。

使用了auto-delete参数声明的交换器只有它关联的所有绑定关系都移除(不管是交换器之间的绑定还是交换器和队列的绑定),它自身才会被删除。举个例子:

  • exchange-source -> exchange-destination -> queue-1

如果exchange-source被删除或者解除与exchange-destination的绑定关系同时exchange-destinationqueue-1解除绑定,而exchange-destination使用了auto-delete参数声明,那么exchange-destination就会被删除。

RabbitMQ中还提供了一个exchange.unbind方法进行交换器之间绑定关系的解除。

编码实现

public class ExchangeBindingMain extends BaseChannelFactory {

public static void main(String[] args) throws Exception {
provideChannel(channel -> {
channel.exchangeDeclare("exchange.source", BuiltinExchangeType.DIRECT, true, false, null);
channel.exchangeDeclare("exchange.destination", BuiltinExchangeType.DIRECT, true, true, null);
channel.queueDeclare("exchange.binding.queue", true, false, false, null);
channel.exchangeBind("exchange.destination", "exchange.source", "exchange.routingKey");
channel.queueBind("exchange.binding.queue", "exchange.destination", "exchange.routingKey");
channel.basicPublish("exchange.source", "exchange.routingKey", MessageProperties.BASIC, "message".getBytes(StandardCharsets.UTF_8));
channel.exchangeUnbind("exchange.destination", "exchange.source", "exchange.routingKey");
// channel.exchangeDelete("exchange.source");
channel.queueUnbind("exchange.binding.queue", "exchange.destination", "exchange.routingKey");
});
}
}

在解除exchange.sourceexchange.destinationexchange.binding.queueexchange.destination之间的绑定后,exchange.destination会自动删除。

(本文完 e-a-20181218 c-1-d)