RabbitMQ交换机(3)-Topic

1.Topic模式

RabbitMQ的Topic模式是一种基于主题的消息传递模式。它允许发送者向一个特定的主题(topic)发布消息,同时,订阅者也可以针对自己感兴趣的主题进行订阅。

在Topic模式中, 主题通过一个由单词和点号组成的字符串来描述。例如,"#.china"表示匹配所有以"china"为结尾的主题,比如"bj.china"或"china"等。( ' # ' 和 ' * ' 会再后面介绍)

当一个消息被发布到Topic交换机(Exchange)时,交换机会将消息转发给所有与该主题匹配的队列。消费者(即订阅者)可以对队列进行绑定,通过指定自己感兴趣的主题进行绑定。

通过使用Topic模式,我们可以实现高度灵活的信息交换模式,同时,确保只有感兴趣的消费者才会收到消息,提高了系统的效率和可靠性。

  1. *匹配1个
  2. #匹配0个或多个
  3. 当一个队列绑定键是#,那么这个队列将接收所有数据,就有点像 fanout 了
  4. 如果队列绑定键当中没有#和*出现,那么该队列绑定类型就是 direct 了

2. 生产者


java 复制代码
package com.hong.rabbitmq8;

import com.hong.utils.RabbitMQUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: Topic模式生产者
 * @Author: hong
 * @Date: 2024-01-16 20:09
 * @Version: 1.0
 **/
public class TopicSend {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtil.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);

        Map<String, String> bindingKeyMap = new HashMap<>();
        bindingKeyMap.put("quick.orange.rabbit", "被队列 Q1Q2 接收到");
        bindingKeyMap.put("lazy.orange.elephant", "被队列 Q1Q2 接收到");
        bindingKeyMap.put("quick.orange.fox", "被队列 Q1 接收到");
        bindingKeyMap.put("lazy.brown.fox", "被队列 Q2 接收到");
        bindingKeyMap.put("lazy.pink.rabbit", "虽然满足两个绑定但只被队列 Q2 接收一次");
        bindingKeyMap.put("quick.brown.fox", "不匹配任何绑定不会被任何队列接收到会被丢弃");
        bindingKeyMap.put("quick.orange.male.rabbit", "是四个单词不匹配任何绑定会被丢弃");
        bindingKeyMap.put("lazy.orange.male.rabbit", "是四个单词但匹配 Q2");

        for (Map.Entry<String, String> bindingKeyEntry : bindingKeyMap.entrySet()) {
            String bindingKey = bindingKeyEntry.getKey();
            String message = bindingKeyEntry.getValue();

            channel.basicPublish(EXCHANGE_NAME, bindingKey, null, message.getBytes(StandardCharsets.UTF_8));
            System.out.println("消息发送完成------" +bindingKey+ message);
        }
    }
}

3.消费者1

java 复制代码
package com.hong.rabbitmq8;

import com.hong.utils.RabbitMQUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

import java.nio.charset.StandardCharsets;

/**
 * @Description: Topic模式接受者1-接收*.orange.*
 * @Author: hong
 * @Date: 2024-01-16 20:07
 * @Version: 1.0
 **/
public class TopicReceiver1 {
    public static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtil.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        String queueName = "Q1";
        channel.queueDeclare(queueName,false,false,false,null);
        channel.queueBind(queueName,EXCHANGE_NAME,"*.orange.*");

        DeliverCallback deliverCallback = (comsumerTag, message) -> {
            System.out.println("接收队列:" + queueName + ",routingKey:" + message.getEnvelope().getRoutingKey() + ",消息:" + new String(message.getBody(), StandardCharsets.UTF_8));
        };

        CancelCallback cancelCallback = var -> {
        };

        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}

4.消费者2

java 复制代码
package com.hong.rabbitmq8;

import com.hong.utils.RabbitMQUtil;
import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.CancelCallback;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DeliverCallback;

import java.nio.charset.StandardCharsets;

/**
 * @Description: Topic模式接受者1-接收*.*.rabbit和lazy.#
 * @Author: hong
 * @Date: 2024-01-16 20:07
 * @Version: 1.0
 **/
public class TopicReceiver2 {
    public static final String EXCHANGE_NAME = "topic_logs";
    public static void main(String[] args) throws Exception {
        Channel channel = RabbitMQUtil.getChannel();
        channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.TOPIC);
        String queueName = "Q2";
        channel.queueDeclare(queueName,false,false,false,null);
        channel.queueBind(queueName,EXCHANGE_NAME,"*.*.rabbit");
        channel.queueBind(queueName,EXCHANGE_NAME,"lazy.#");

        DeliverCallback deliverCallback = (comsumerTag, message) -> {
            System.out.println("接收队列:" + queueName + ",routingKey:" + message.getEnvelope().getRoutingKey() + ",消息:" + new String(message.getBody(), StandardCharsets.UTF_8));
        };

        CancelCallback cancelCallback = var -> {
        };

        channel.basicConsume(queueName,true,deliverCallback,cancelCallback);
    }
}



例子 说明
quick.orange.rabbit 被队列 Q1Q2 接收到
lazy.orange.elephant 被队列 Q1Q2 接收到
quick.orange.fox 被队列 Q1 接收到
lazy.brown.fox 被队列 Q2 接收到
lazy.pink.rabbit 虽然满足两个绑定但只被队列 Q2 接收一次
quick.brown.fox 不匹配任何绑定不会被任何队列接收到会被丢弃
quick.orange.male.rabbit 是四个单词不匹配任何绑定会被丢弃
lazy.orange.male.rabbit 是四个单词但匹配 Q2
相关推荐
隔壁阿布都19 小时前
ShedLock 分布式定时任务锁框架介绍
spring boot·分布式
文艺倾年19 小时前
【强化学习】数学推导专题,20W字总结(十五)
人工智能·分布式·大模型·强化学习·vibecoding
ACP广源盛139246256732 天前
GSV5600@ACP#多接口协议转换芯片,物理 AI 便携终端的互联核心
大数据·人工智能·分布式·嵌入式硬件·spark
极客先躯2 天前
高级java每日一道面试题-2026年02月12日-实战篇[Docker]-什么是容器的 Seccomp 配置?如何自定义?
java·运维·分布式·docker·容器·自动化·文件
Francek Chen2 天前
【大数据处理与分析】MapReduce:06 MapReduce编程实践
大数据·hadoop·分布式·mapreduce
小马爱打代码2 天前
Kafka消息队列监控:Topic积压、吞吐量、Broker负载及消费者组全观测
分布式·kafka
半夜修仙2 天前
延迟队列的介绍及常见问题
java·数据库·中间件·rabbitmq
轻口味2 天前
轻规划鸿蒙开发实战10:分布式数据同步深度博弈,UserId 隔离与并发数据冲突消解机
分布式·华为·harmonyos·鸿蒙
Solis程序员2 天前
Raft:分布式系统的定海神针
java·分布式·kafka·rabbitmq·agent·raft
手握风云-2 天前
一条消息的旅程:RabbitMQ 学习与实践(一)
中间件·rabbitmq