消息队列(2) | 青训营笔记

32 阅读2分钟

今日学习,消息队列(2),Direct和Topic。分布式搜索引擎ElasticSearch和Lucene

  • Fanout模式中,一条消息,会被所有订阅的队列都消费,但是在某些场景下,我们希望不同的消息被不同的队列消费,这时就要用到Direct类型的Exchange

  • Direct模型下

    • 队列与虚拟机绑定,不能是任意绑定了,而是需要指定一个RoutingKey(路由key)
    • 消息的发送方在向Exchange发送消息时,也必须指定消息的RoutingKey
    • Exchange不再把消息交给每一个绑定的队列,而是根据消息的RoutingKey进行判断,只有队列的RoutingKey与消息的RoutingKey完全一致,才会收到消息

除了基于Bean声明队列和交换机,还有基于注解的形式

  • 基于@RabbitListener注解声明队列和交换机有哪些常见的注解?

    • @QueueBinding
    • @Queue
    • @Exchange

    在Consumer类中RabbitListener:

    /**
     * 除了基于Bean声明队列和交换机,还有基于注解的形式
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue1"),
            exchange = @Exchange(name = "directExchange", type = ExchangeTypes.DIRECT),
            key = {"Apex", "DeepRock"}
    ))
    public void listenDirectQueue1(String msg) {
        System.out.println("[基于注解的Direct]消费者收到direct.queue1的消息:【" + msg + "】");
    }
    
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue2"),
            exchange = @Exchange(name = "directExchange", type = ExchangeTypes.DIRECT),
            key = {"Apex", "Terraria"}
    ))
    public void listenDirectQueue2(String msg) {
        System.out.println("[基于注解的Direct]消费者收到direct.queue2的消息:【" + msg + "】");
    }
    
    /**
     * 使用Direct
     */
    @Test
    public void testSendDirectExchange() {
        // 交换机名称
        String exchangeName = "itcast.direct";
        // 消息
        String message = "hello, red!";
        String message1 = "hello, yellow!";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName, "red", message);
        rabbitTemplate.convertAndSend(exchangeName, "yellow", message1);
    }
    //可以看到red在queue两个都有,但是yellow只在queue2有(即只出现一次) 


Topic

  • Topic类型的Exchange与Direct相比,都是可以根据RoutingKey把消息路由到不同的队列,只不过Topic类型的Exchange可以rag队列绑定Routing Key的时候使用通配符

  • Routing Key一般都是由一个或多个单词组成,多个单词间以.分割,例如item.insert

  • 通配符规则

    • #:匹配一个或多个词
    • *:仅匹配一个词

消息转换器

默认情况下,Spring采用的序列化方式是JDK序列化

  • 配置JSON转换器