全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-22 8 分钟 ✍️ juanwangdev

Topic通配符规则

Topic通配符规则定义消息路由键与绑定键的模式匹配逻辑,实现灵活的多条件路由。

定义

Topic交换机使用两种通配符进行路由键匹配:*匹配恰好一个单词段,#匹配零个或多个单词段。路由键以点号.分隔形成层级结构的单词序列。

通配符语法

基础规则

通配符匹配规则示例
*匹配一个单词段stock.*匹配stock.usd,不匹配stock.usd.nyse
#匹配零个或多个单词段stock.#匹配stockstock.usdstock.usd.nyse

匹配示例

Java
绑定键: order.us.*
  匹配: order.us.created ✓
        order.us.updated ✓
  不匹配: order.eu.created ✗
          order.us.nyse.created ✗

绑定键: order.#
  匹配: order ✓
        order.us ✓
        order.us.created ✓
        order.us.nyse.pending ✓

绑定键: *.critical
  匹配: order.critical ✓
        payment.critical ✓
  不匹配: critical ✗(需要前面有一个单词段)
          order.high.critical ✗

完整示例

Java
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import java.util.HashMap;
import java.util.Map;

public class TopicWildcardExample {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        
        try (Connection connection = factory.newConnection();
             Channel channel = connection.createChannel()) {
            
            channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);
            
            // 声明队列并绑定不同通配符模式
            channel.queueDeclare("queue_all", true, false, false, null);
            channel.queueDeclare("queue_us", true, false, false, null);
            channel.queueDeclare("queue_errors", true, false, false, null);
            channel.queueDeclare("queue_payments", true, false, false, null);
            
            // 通配符绑定示例
            channel.queueBind("queue_all", EXCHANGE_NAME, "#");              // 接收所有消息
            channel.queueBind("queue_us", EXCHANGE_NAME, "*.us.*");          // 匹配中间为us的三段路由键
            channel.queueBind("queue_errors", EXCHANGE_NAME, "*.error");     // 匹配以error结尾的两段路由键
            channel.queueBind("queue_payments", EXCHANGE_NAME, "payment.#"); // 匹配所有payment开头的消息
            
            System.out.println("Topic bindings configured");
            
            // 测试不同路由键的消息分发
            String[] testRoutingKeys = {
                "order.us.created",      // -> queue_all, queue_us
                "order.eu.created",      // -> queue_all
                "payment.error",         // -> queue_all, queue_errors
                "payment.us.refund",     // -> queue_all, queue_us, queue_payments
                "system.warning",        // -> queue_all
                "critical.error"         // -> queue_all, queue_errors
            };
            
            for (String routingKey : testRoutingKeys) {
                String message = "Test message for " + routingKey;
                channel.basicPublish(EXCHANGE_NAME, routingKey, null, 
                        message.getBytes("UTF-8"));
                System.out.println("Published: " + routingKey);
            }
        }
    }
}

消费者配置

text
import com.rabbitmq.client.*;

public class TopicConsumer {
    private static final String EXCHANGE_NAME = "topic_logs";

    public static void main(String[] args) throws Exception {
        ConnectionFactory factory = new ConnectionFactory();
        factory.setHost("localhost");
        
        Connection connection = factory.newConnection();
        Channel channel = connection.createChannel();
        
        channel.exchangeDeclare(EXCHANGE_NAME, "topic", true);
        
        // 使用临时队列接收特定模式的消息
        String queueName = channel.queueDeclare().getQueue();
        
        // 绑定通配符路由键
        channel.queueBind(queueName, EXCHANGE_NAME, "order.*.created");
        
        System.out.println("Waiting for order creation messages...");
        
        DeliverCallback deliverCallback = (consumerTag, delivery) -> {
            String message = new String(delivery.getBody(), "UTF-8");
            String routingKey = delivery.getEnvelope().getRoutingKey();
            System.out.println("[" + routingKey + "] " + message);
            channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);
        };
        
        channel.basicConsume(queueName, false, deliverCallback, consumerTag -> {});
    }
}

注意事项

  • #可匹配零个单词段,stock.#可匹配stock本身
  • *必须匹配恰好一个单词段,stock.*不匹配stock本身
  • 路由键单词段建议使用小写字母和数字,避免特殊字符导致匹配异常
  • Topic交换机匹配性能随绑定数量增加而下降,建议控制绑定总数
  • 通配符匹配是贪婪的,#会尽可能匹配更多单词段

要点总结

  • *匹配恰好一个单词段,#匹配零个或多个单词段
  • 路由键以点号分隔,形成层级结构便于通配符匹配
  • #作为绑定键时接收所有消息,等效于Fanout交换机
  • 通配符匹配性能随绑定数量增加而下降,需合理设计路由结构
  • 适用于多条件过滤、主题分类、层级路由等灵活路由场景

文章存放路径:D:\git2\jwdev\articles\RABBITMQ\进阶\消息路由与绑定\Topic通配符规则.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 默认交换机
下一篇 → 动态绑定管理
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库