RabbitMQ 主题交换机
topic(主题)交换机按"模式匹配"路由:binding key 里允许通配符,把一个模式对应的整类 routing key 收进来,是三种常用交换机中最灵活的。
路由语义与通配符
routing key 用点 . 分隔成若干"词"(word),binding key 中可用两个通配符:
| 通配符 | 含义 | 示例 binding key |
|---|---|---|
| * | 恰好匹配一个词 | log.*.error |
| # | 匹配零个或多个词 | log.# |
没有通配符的词按字面精确匹配(同 direct)。消息会复制给所有匹配成功的绑定队列;topic 的 routing key 整条最长 255 字节,超出会发布失败。
通配符匹配示例
假设发布三类消息:user.created、user.updated、user.order.paid,各 binding key 的命中结果如下:
| binding key | user.created | user.updated | user.order.paid |
|---|---|---|---|
| user.* | 命中 | 命中 | 不命中(三段 key,* 只占一段) |
| user.# | 命中 | 命中 | 命中 |
| *.created | 命中 | 不命中 | 不命中 |
| #.paid | 不命中 | 不命中 | 命中 |
| # | 命中 | 命中 | 命中 |
典型写法:用户事件分流
用户服务发两类事件,一个队列只要"创建",另一个队列全要:
import pika
conn = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
ch = conn.channel()
ch.exchange_declare(exchange='user.topic', exchange_type='topic', durable=True)
ch.queue_declare(queue='user.created.q', durable=True)
ch.queue_declare(queue='user.all.q', durable=True)
ch.queue_bind(queue='user.created.q', exchange='user.topic', routing_key='user.created')
ch.queue_bind(queue='user.all.q', exchange='user.topic', routing_key='user.#')
ch.basic_publish(exchange='user.topic', routing_key='user.created', body=b'u100 created')
ch.basic_publish(exchange='user.topic', routing_key='user.updated', body=b'u100 updated')
# 输出:user.created 只进 user.created.q;两条消息都进 user.all.q
conn.close()
典型写法:两级日志键
日志用"系统.级别"做 routing key,一个 binding 就能收所有系统的 error:
facility.severity 两级键示例:
binding "*.error" ← 收所有系统的 error(web.error、pay.error、task.error ...)
binding "pay.*" ← 只收支付系统所有级别
binding "#" ← 全收(调试用,慎用)
# 与 * 辨析
-
- 只代表"一个词":user.* 收 user.created,收不了 user.created.v1;
-
代表"任意多个词(含 0 个)":user.# 能收 user.created,也能收 user.created.v1,连单词 user 本身也收;
- 两者可混用:*.log.# 表示"第一段任意、之后以 log 开头再接任意内容"。
注意事项
- 发布到 topic 交换机的消息,routing key 不能为空:空 key 的消息无法匹配,会被直接丢弃;
- 通配符只在 binding key 里有特殊含义:生产者在 routing key 里写 * 或 # 会被当成普通字符处理,属于反模式,应使用明确的事件键;
- 通配符按"词"整段生效,不能嵌在词里做字符级模糊:* 与 # 必须各自独占一个词,例如 binding key 写成 u*.created,其中的 * 不被识别为通配、只会按字面字符匹配,几乎永远命中不了;需要"任意用户"应把键设计成 *.created 这类整段通配,或让生产者统一键格式。
小结
topic 交换机用 * 和 # 按段匹配 routing key,一个绑定收一类消息,是 direct 的"模糊升级版"(不含通配符时行为与 direct 相同)。至此三类常用交换机讲完,下一章 headers 交换机用消息头做多条件匹配,适用于更复杂的组合条件。