Rabbitmq fanout与topic区别

RabbitMQ服务器会根据路由键将消息从交换器路由到队列中,如何处理投递到多个队列的情况?这里不同类型的交换器起到了重要的作用。

最常用的交换机有三种:direct、topic、fanout。我分别叫他们:“直接连接交换机”,“主题路由匹配交换机”,“无路由交换机”

fanout

fanout类型的Exchange路由规则非常简单,它会把所有发送到该Exchange的消息路由到所有与它绑定的Queue中。

Rabbitmq fanout与topic区别_第1张图片

上图中,生产者(P)发送到Exchange(X)的所有消息都会路由到图中的两个Queue,并最终被两个消费者(C1与C2)消费。

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = QueueName, durable = "true", ignoreDeclarationExceptions = "true"),
            exchange = @Exchange(value = EventConfig.exchangeGR, type = ExchangeTypes.FANOUT, durable = "true"),
            ignoreDeclarationExceptions = "true"))
    public void saveReapirTestee(@Payload Event event, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag){
        try {
            service.saveInventory(Event,0001L, "系统消息实时生成");
            log.info("save  maintain receive inventory succeed");
            channel.basicAck(deliveryTag, false);
        }catch (Exception e){
            log.info("save receive inventory failed !");
            log.info("save receive inventory json -->"+JSONObject.toJSONString(goodsReciptEvent));
            try {
                channel.basicAck(deliveryTag, false);
            }catch (Exception ee){
                log.error("save receive inventory failed !",e);
            }

        }

    }

direct

direct类型的Exchange路由规则也很简单,它会把消息路由到那些binding key与routing key完全匹配的Queue中。

Rabbitmq fanout与topic区别_第2张图片

以上图的配置为例,我们以routingKey=”error”发送消息到Exchange,则消息会路由到Queue1(amqp.gen-S9b…,这是由RabbitMQ自动生成的Queue名称)和Queue2(amqp.gen-Agl…);如果我们以routingKey=”info”或routingKey=”warning”来发送消息,则消息只会路由到Queue2。如果我们以其他routingKey发送消息,则消息不会路由到这两个Queue中。

topic

前面讲到direct类型的Exchange路由规则是完全匹配binding key与routing key,但这种严格的匹配方式在很多情况下不能满足实际业务需求。topic类型的Exchange在匹配规则上进行了扩展,它与direct类型的Exchage相似,也是将消息路由到binding key与routing key相匹配的Queue中,但这里的匹配规则有些不同,它约定:

  • routing key为一个句点号“. ”分隔的字符串(我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词),如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
  • binding key与routing key一样也是句点号“. ”分隔的字符串
  • binding key中可以存在两种特殊字符“*”与“#”,用于做模糊匹配,其中“*”用于匹配一个单词,“#”用于匹配多个单词(可以是零个)

Rabbitmq fanout与topic区别_第3张图片

以上图中的配置为例,routingKey=”quick.orange.rabbit”的消息会同时路由到Q1与Q2,routingKey=”lazy.orange.fox”的消息会路由到Q1与Q2,routingKey=”lazy.brown.fox”的消息会路由到Q2,routingKey=”lazy.pink.rabbit”的消息会路由到Q2(只会投递给Q2一次,虽然这个routingKey与Q2的两个bindingKey都匹配);routingKey=”quick.brown.fox”、routingKey=”orange”、routingKey=”quick.orange.male.rabbit”的消息将会被丢弃,因为它们没有匹配任何bindingKey。

    @RabbitListener(bindings = @QueueBinding(
            key =  "snStockStatus" + StringConstant.QUEUE_NORMAL,
            value = @Queue(value = snQueue, durable = "true", ignoreDeclarationExceptions = "true"),
            exchange = @Exchange(value = EventConfig.exchangeSROC, type = ExchangeTypes.TOPIC, durable = "true"),
            ignoreDeclarationExceptions = "true"))
    public void snStockReservedAvailable(@Payload Event event, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) throws IOException {
        try {
            service.reservedAvailable(event);
            channel.basicAck(deliveryTag, false);
        } catch (IOException e1) {
            log.error(MQ错误{}", e1+JSONObject.toJSONString(event));
        }
    }

 

你可能感兴趣的:(MQ)