RabbitMQ三种交换机的基本使用方法

RabbitMQ 中的交换机(Exchange)是消息路由的核心组件,它负责将生产者发送的消息根据一定的路由规则分发到队列。RabbitMQ 提供了三种常见的交换机类型:**Direct Exchange**、**Fanout Exchange** 和 **Topic Exchange**。每种交换机类型都有不同的路由方式,适用于不同的场景。

1. **Direct Exchange** (直接交换机)

1.1 介绍

  • **Direct Exchange** 是最常见的交换机类型,它根据消息的 **Routing Key**(路由键)将消息路由到一个或多个匹配的队列。

  • 如果队列绑定时指定了特定的路由键,那么只有生产者发送的消息的路由键与该队列绑定的路由键完全匹配时,消息才会被路由到该队列。

1.2 用法

  • **适用场景**:适用于发送特定消息到特定队列的场景。

  • **消息路由**:通过 `Routing Key` 来精确匹配队列。

1.3 配置和使用

```java

@Bean

public DirectExchange directExchange() {

return new DirectExchange("directExchange", true, false); // durable,是否持久化

}

@Bean

public Binding transferFileBinding(Queue transferFileQueue, DirectExchange directExchange) {

return BindingBuilder.bind(transferFileQueue)

.to(directExchange)

.with("transferFileRoutingKey");

}

```

  • **消息发送**:指定交换机名称、路由键发送消息。

```java

amqpTemplate.convertAndSend("directExchange", "transferFileRoutingKey", message);

```

1.4 消息路由示例

假设有两个队列绑定到 `directExchange`:

  • 队列 `queue1` 绑定路由键为 `key1`

  • 队列 `queue2` 绑定路由键为 `key2`

如果生产者发送消息时设置路由键为 `key1`,那么只有 `queue1` 会接收到该消息;如果路由键为 `key2`,则 `queue2` 会接收到。


2. **Fanout Exchange** (扇出交换机)

2.1 介绍

  • **Fanout Exchange** 将接收到的消息广播到所有绑定到该交换机的队列,而不关心消息的路由键。

  • 它不会使用路由键,而是将消息发给所有的消费者队列。

2.2 用法

  • **适用场景**:适用于广播消息的场景,例如推送消息、实时通知等。

  • **消息路由**:与路由键无关,消息会被广播到所有绑定的队列。

2.3 配置和使用

```java

@Bean

public FanoutExchange fanoutExchange() {

return new FanoutExchange("fanoutExchange", true, false); // durable,是否持久化

}

@Bean

public Binding binding1(Queue queue1, FanoutExchange fanoutExchange) {

return BindingBuilder.bind(queue1).to(fanoutExchange);

}

```

  • **消息发送**:发送到交换机,不需要指定路由键。

```java

amqpTemplate.convertAndSend("fanoutExchange", "", message); // 路由键为空

```

2.4 消息路由示例

假设有两个队列绑定到 `fanoutExchange`,无论消息的内容是什么,消息都会同时发送到这两个队列。

  • 队列 `queue1` 和 `queue2` 都绑定到 `fanoutExchange`,生产者发送一条消息时,这条消息会同时发送到 `queue1` 和 `queue2`。

3. **Topic Exchange** (主题交换机)

3.1 介绍

  • **Topic Exchange** 允许根据 **Routing Key** 中的部分匹配规则来路由消息。

  • 它支持更灵活的消息路由,可以使用通配符(`*` 和 `#`)来匹配多个路由键。

  • `*`:匹配一个词

  • `#`:匹配零个或多个词

3.2 用法

  • **适用场景**:适用于需要复杂路由逻辑的场景,比如根据多个维度(如日志级别、类别等)进行消息路由。

  • **消息路由**:通过路由键的模式匹配来决定消息发送到哪些队列。

3.3 配置和使用

```java

@Bean

public TopicExchange topicExchange() {

return new TopicExchange("topicExchange", true, false); // durable,是否持久化

}

@Bean

public Binding binding1(Queue queue1, TopicExchange topicExchange) {

return BindingBuilder.bind(queue1)

.to(topicExchange)

.with("*.log.*"); // 匹配类似 "error.log.java" 这样的路由键

}

```

  • **消息发送**:发送消息时指定路由键,支持多层级的通配符。

```java

amqpTemplate.convertAndSend("topicExchange", "error.log.java", message);

```

3.4 消息路由示例

假设有以下两个队列绑定到 `topicExchange`:

  • 队列 `queue1` 绑定的路由键模式是 `*.log.*`,表示它会接收以 `.log.` 为中间部分的路由键(如 `error.log.java`、`info.log.js`)。

  • 队列 `queue2` 绑定的路由键模式是 `*.error`,表示它会接收以 `.error` 结尾的路由键(如 `critical.error`)。

如果生产者发送消息,路由键为 `error.log.java`,那么:

  • `queue1` 会接收到消息(因为路由键匹配 `*.log.*`)。

  • `queue2` 不会接收到该消息(因为路由键不匹配 `*.error`)。


比较和选择

| 交换机类型 | 路由规则 | 适用场景 |

|-------------------|----------|-----------------------------------------------|

| **Direct Exchange** | 精确匹配 `Routing Key` | 消息发送到特定队列,如任务分发等 |

| **Fanout Exchange** | 广播到所有队列 | 广播通知、实时推送等 |

| **Topic Exchange** | 基于模式匹配的 `Routing Key` | 复杂的路由需求,如按日志级别、类别分发等 |

结论

  • **Direct Exchange**:适用于一对一的精确消息路由。

  • **Fanout Exchange**:适用于消息广播到所有订阅的队列。

  • **Topic Exchange**:适用于灵活、复杂的消息路由,支持路由键的通配符匹配。

根据实际业务需求,选择合适的交换机类型,可以帮助更高效地实现消息传递和路由策略。

相关推荐
cici1587443 分钟前
MyBatis注解的运用于条件搜索实践
java·tomcat·mybatis
wangqiaowq1 小时前
StarRocks安装部署测试
java·开发语言
计算机学姐1 小时前
基于SpringBoot的高校社团管理系统【协同过滤推荐算法+数据可视化】
java·vue.js·spring boot·后端·mysql·信息可视化·推荐算法
工业甲酰苯胺5 小时前
实现 json path 来评估函数式解析器的损耗
java·前端·json
老前端的功夫5 小时前
Web应用的永生之术:PWA落地与实践深度指南
java·开发语言·前端·javascript·css·node.js
@forever@5 小时前
【JAVA】LinkedList与链表
java·python·链表
程序员爱钓鱼5 小时前
Python编程实战:面向对象与进阶语法——类型注解与代码规范(PEP 8)
后端·python·ipython
程序员爱钓鱼5 小时前
Python实战:用高德地图API批量获取地址所属街道并写回Excel
后端·python·ipython
LilySesy5 小时前
ABAP+WHERE字段长度不一致报错解决
java·前端·javascript·bug·sap·abap·alv
六件套是我5 小时前
redission实现延时队列
android·java·servlet