RabbitMQ入门指南(四):交换机与案例解析

前言

RabbitMQ是一个高效、可靠的开源消息队列系统,广泛用于软件开发、数据传输、微服务等领域。本文主要介绍了交换机在RabbitMQ中的作用与类型、交换机案例(Fanout交换机、Direct交换机、Topic交换机)等内容。


一、交换机在RabbitMQ中的作用与类型

在RabbitMQ中,交换机是一个核心组件,它起到了连接生产者、队列和交换机之间的桥梁作用。交换机的存在改变了消息发送的模式,它接收生产者的消息,并根据特定的路由规则,将消息转发到相应的队列。

案例模型:

交换机的类型:

  • Fanout交换机

    • 类型:广播
    • 功能:将消息发送给所有绑定到交换机的队列。这意味着,无论队列是否订阅了消息,只要它们与交换机绑定,它们都会收到消息。
    • 示例:如果有一个Fanout交换机,并且有两个队列A和B分别绑定到了这个交换机上。当生产者向这个交换机发送消息时,A和B两个队列都会收到这条消息。
  • Direct交换机

    • 类型:订阅
    • 功能:基于RoutingKey(路由键)将消息发送给订阅了相应RoutingKey的队列。如果一个队列没有订阅某个RoutingKey的消息,那么它就不会收到这个消息。
    • 示例:假设有两个队列A和B,它们都订阅了RoutingKey为"key1"的消息。如果有一个Direct交换机,并且它接收到一条RoutingKey为"key1"的消息,那么这条消息会被发送到A和B两个队列。
  • Topic交换机

    • 类型:通配符订阅
    • 功能:基于RoutingKey(路由键)发送消息给订阅了与RoutingKey匹配的队列。与Direct交换机不同的是,RoutingKey可以使用通配符。
    • 示例:假设有两个队列A和B,A订阅了"key.#"的消息,B订阅了"key.*"的消息。如果有一个Topic交换机,并且它接收到一条RoutingKey为"key.test"的消息,那么这条消息会被发送到A和B两个队列。
  • Headers交换机

    • 类型:头匹配
    • 功能:基于消息的头部属性进行匹配,将消息发送给匹配了这些属性的队列。这种类型的交换机使用的较少。

交换机的选择和使用:

在选择和使用交换机时,需要根据业务需求和场景来决定使用哪种类型的交换机。如果需要将消息广播给所有相关的队列,那么Fanout交换机是一个很好的选择。如果需要根据特定的RoutingKey将消息发送给特定的队列,那么Direct或Topic交换机是合适的选择。而Headers交换机由于其较少的使用场景和特定的行为,通常在特定的情况下才会使用。

二、交换机案例

1.Fanout交换机(广播

案例模型:

  • 多个队列:在这种模式下,可以存在多个队列,这些队列都绑定到同一个交换器上。
  • 队列与交换器的绑定:每个队列都需要绑定到至少一个交换器上。这是消息路由的关键步骤,因为只有绑定了交换器的队列才能接收来自该交换器的消息。
  • 生产者发送消息:生产者将消息发送到交换机,而不是直接发送到队列。这意味着生产者不需要知道关于队列的任何信息,只需要知道交换器的存在和如何将消息发送到交换器。
  • 交换机的行为:当交换机接收到来自生产者的消息时,它会将这个消息发送到所有与该交换机绑定的队列。这是一个非常强大的特性,因为它允许一个消息被广播到多个队列,每个队列都可以有自己的消费者来处理这个消息。
  • 消费者接收消息:如果一个或多个消费者订阅了某个队列,那么他们都可以接收到来自该队列的消息。这意味着消费者不需要知道关于交换机的任何信息,只需要知道如何订阅和接收来自特定队列的消息。

在RabbitMQ管理控制台新建两个队列:

查看新建结果:

新建一个交换机,选择fanout类型:

查看新建结果:

绑定两个队列到交换机:

查看绑定结果:

在publisher服务中的测试类添加一个测试方法,实现消息发送

ini 复制代码
    @Test
    void testSendFanout() {
        String exchangeName = "demo.fanout";
        String msg = "Fanout Exchange test";
        rabbitTemplate.convertAndSend(exchangeName, null, msg);
    }

在consumer服务的类中添加2个新的方法,作为消费者:

typescript 复制代码
    @RabbitListener(queues = "fanout1.queue")
    public void listenFanoutQueue1(String msg) {
        System.out.println("fanout1:" + msg);
    }

    @RabbitListener(queues = "fanout2.queue")
    public void listenFanoutQueue2(String msg) {
        System.out.println("fanout2" + msg);
    }

运行结果:

2.Direct交换机(订阅

案例模型:

在Direct模型中,消息并不是被发送到所有绑定的队列,而是基于一个特定的路由键(RoutingKey)来决定其目的地。这种模型的好处是提供了更高的灵活性和控制性。通过使用不同的RoutingKey,可以将消息发送到特定的队列,从而实现更复杂的消息处理逻辑。

  • 队列与交换机的绑定 :在Direct模型下,队列与交换机的绑定不再是任意的。当队列绑定到交换机时,必须指定一个**RoutingKey。这个 RoutingKey**可以被看作是决定消息路由的"标签"或"地址"。
  • 消息的发送与路由键 :当消息的发送方(生产者)向交换机发送消息时,它必须为该消息指定一个**RoutingKey。这个 RoutingKey**代表了消息的预期目的地或类别。
  • Exchange的消息路由决策 :与Fanout模型不同,Direct模型中的交换机并不会将接收到的消息发送给所有绑定的队列。相反,它会查看每个消息的**RoutingKey,并与绑定时设置的 RoutingKey进行比较。只有当队列的 RoutingKey与消息的 RoutingKey**完全匹配时,该队列才会接收到这个消息。

在RabbitMQ管理控制台新建两个队列:

查看新建结果:

新建一个交换机,选择direct类型:

查看新建结果:

绑定两个队列到交换机,指定RoutingKey:

查看绑定结果:

在consumer服务的类中添加2个新的方法,作为消费者进行消息接收

typescript 复制代码
    @RabbitListener(queues = "direct1.queue")
    public void listenDirectQueue1(String msg) {
        System.out.println("direct1:" + msg);
    }

    @RabbitListener(queues = "direct2.queue")
    public void listenDirectQueue2(String msg) {
        System.out.println("direct2:" + msg);
    }

在publisher服务中的测试类添加一个测试方法,设置RoutingKeyred ,实现消息发送

typescript 复制代码
    @Test
    public void testSendDirectExchange() {
        // 交换机名称
        String exchangeName = "demo.direct";
        // 消息
        String message = "Direct Exchange Red test";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName, "red", message);
    }

运行结果:

在publisher服务中的测试类修改测试方法,设置RoutingKeyblue

typescript 复制代码
    @Test
    public void testSendDirectExchange() {
        // 交换机名称
        String exchangeName = "demo.direct";
        // 消息
        String message = "Direct Exchange Red test";
        // 发送消息
        rabbitTemplate.convertAndSend(exchangeName, "blue", message);
    }

运行结果(只有消费者1收到了消息 ):

3.Topic交换机(通配符订阅

案例模型:

在RabbitMQ的Topic模型中,消息的路由规则更加灵活和高级。与Direct模型不同,Topic模型允许使用通配符来进行路由键匹配。通过使用通配符,可以匹配多个队列,从而实现更复杂的消息处理逻辑。

  • 队列与交换机的绑定 :在Topic模型下,队列与交换机的绑定仍然需要指定一个**RoutingKey。然而,这个 RoutingKey**可以包含通配符,以提供更广泛的匹配选项。
  • 消息的发送与路由键 :当消息的发送方(生产者)向交换机发送消息时,它仍然需要为该消息指定一个**RoutingKey。这个 RoutingKey**可以包含通配符,以便在多个队列之间进行匹配。
  • 交换机和路由决策 :在Topic模型中,交换机会查看每个消息的**RoutingKey,并与绑定时设置的 RoutingKey进行比较。如果消息的 RoutingKey与队列的 RoutingKey**匹配(包括使用通配符进行匹配),则该队列会接收到这个消息。

在RabbitMQ管理控制台新建两个队列:

查看新建结果:

新建一个交换机,选择Topic类型:

查看新建结果:

绑定两个队列到交换机,指定RoutingKey:

查看绑定结果:

在consumer服务的类中添加2个新的方法,作为消费者进行消息接收

java 复制代码
    @RabbitListener(queues = "topic1.queue")
    public void listenTopicQueue1(String msg) throws InterruptedException {
        System.out.println("topic1:" + msg);
    }

    @RabbitListener(queues = "topic2.queue")
    public void listenTopicQueue2(String msg) throws InterruptedException {
        System.out.println("topic1:" + msg);
    }

在publisher服务中的测试类添加一个测试方法,设置RoutingKeychina.news ,实现消息发送

ini 复制代码
    @Test
    void testSendTopic() {
        String exchangeName = "demo.topic";
        String msg = "Topic Exchange test1";
        rabbitTemplate.convertAndSend(exchangeName, "china.news", msg);
    }

运行结果:

在publisher服务中的测试类修改测试方法,设置RoutingKeychina.date

ini 复制代码
    @Test
    void testSendTopic() {
        String exchangeName = "demo.topic";
        String msg = "Topic Exchange test";
        rabbitTemplate.convertAndSend(exchangeName, "china.date", msg);
    }

运行结果(只有消费者1收到了消息 ):


总结

RabbitMQ是一个开源的消息队列软件,旨在提供可靠的消息传递和消息队列功能。本文主要介绍了交换机在RabbitMQ中的作用与类型、交换机案例(Fanout交换机、Direct交换机、Topic交换机)等内容,希望对大家有所帮助。

相关推荐
追逐时光者4 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_4 小时前
敏捷开发流程-精简版
前端·后端
苏打水com5 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧6 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧6 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧6 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧6 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧6 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng7 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6017 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring