切换主题
11. 过滤与业务路由:别让每个服务都收到所有消息
产品把通知做细了
通知服务说:
我只关心订单创建和订单关闭。支付、发货、退款这些消息我不想处理。
仓库服务说:
我只关心支付成功和取消订单。
这时就要做好过滤和业务路由。
基础路由策略
订单域可以先设计一个 topic:
text
Topic: order-event-topic
Tags:
order-created
order-paid
order-closed
order-cancelled
order-shipped不同服务订阅不同 tag:
| 服务 | 订阅 |
|---|---|
| 通知服务 | order-created、order-closed |
| 仓储服务 | order-paid、order-cancelled |
| 积分服务 | order-paid |
| 风控服务 | * |
教学示例中先使用单 tag 或 *。复杂表达式要根据当前 RocketMQ 服务端和客户端能力验证后再用。
发送时带 Tag 和 Key
java
Message<OrderPaidEvent> message = MessageBuilder
.withPayload(event)
.setHeader(RocketMQHeaders.TAGS, "order-paid")
.setHeader(RocketMQHeaders.KEYS, event.orderId())
.build();
rocketMQClientTemplate.syncSendNormalMessage("order-event-topic", message);业务路由不要只靠消费者 if
差写法:
java
if (!"order-paid".equals(event.type())) {
return;
}这会让消费者收到大量无关消息。应该优先用 topic/tag 做粗过滤,业务代码里再做二次校验。
小技巧
Topic 和 Tag 命名要稳定。建议用业务事实,不用页面名称:
| 不推荐 | 推荐 |
|---|---|
order-page-click | order-created |
send-sms | order-paid |
warehouse-api | fulfillment-requested |
消息是系统之间的契约,不是某个页面或接口的影子。
常见坑
所有服务订阅
*。
前期省事,后期消费压力和误处理风险都会上来。Tag 设计成状态机全部细节。
Tag 是粗过滤。复杂条件可以放 payload 或业务查询。Key 不统一。
有的用orderId,有的用paymentNo,排查时会混乱。
练习题
- 仓储服务应该订阅哪些订单事件?
- 为什么
send-sms不适合作为订单事件 tag? - 如果一个服务需要所有订单事件,应该怎么订阅?
参考答案
- 通常订阅
order-paid和order-cancelled,具体看库存和履约模型。 - 因为它描述的是消费动作,不是业务事实。
- 可以订阅
*,但要确认它确实承担全量事件处理职责,例如风控或审计。