NATS/JetStream中命令所用Subject主题的通用命名规范咨询
NATS/JetStream CQRS场景命令Subject命名规范参考
NATS官方本身没有强制的命名标准,但CQRS/事件溯源落地场景下,社区已经形成了一套和JetStream特性、DDD分层逻辑高度适配的通用命名约定,完全可以和你现有的事件命名体系统一,不需要推翻原有设计。
核心底层原则
所有命名都要适配NATS本身的通配符匹配逻辑:*匹配单个层级,>匹配后续所有层级,所以层级从左到右要遵循「范围从宽到窄」的规则:
- 所有分段统一用小写字母,单词间用短横线连接,不要用驼峰、下划线、特殊字符
- 单个分段只承载单一维度语义,不要在一个分段里塞多个信息
- 命令、事件、查询类消息的前缀层级保持完全一致,方便统一做流配置、权限管控、流量观测
- 不要在分段里用无意义的缩写,避免后续维护时出现语义歧义
命令场景推荐分层结构(兼容你现有命名逻辑)
你当前用的myProjectName.internal.pricing缺少消息类型、目标聚合两个核心语义层,长期迭代很容易出现subject冲突、通配符匹配混乱的问题,推荐统一用如下分层结构:
<项目标识>.<消息类型>.<边界上下文>.<聚合根>.<动作指令>.<可选扩展段>
各分段语义说明:
- 第一层:项目/系统名,和你现有规则保持一致,比如
myProjectName - 第二层:消息类型,替换你原来放
internal的位置:命令固定写cmd,事件固定写evt,查询类消息固定写qry。不推荐把internal/public这类访问范围标识放在第二层,访问范围完全可以通过NATS的权限系统控制,放在第二层会破坏通配符匹配的一致性——比如要订阅整个项目所有命令,直接写myProjectName.cmd.>即可,不需要额外区分内外 - 第三层:DDD边界上下文标识,比如定价域就是
pricing、订单域就是order、用户域就是user - 第四层:命令目标的聚合根,比如定价域下的商品定价聚合就是
product-price、费率聚合就是rate - 第五层:具体的命令动作,统一用祈使语气的动词,比如定价计算用
calculate、定价更新用update、定价审批用approve - 可选扩展段:如果有多租户、多环境隔离需求,统一放在最后,比如
prod、tenant-123
给几个适配你定价场景的实际命名样例:
# 定价域-商品定价聚合-触发定价计算命令 myProjectName.cmd.pricing.product-price.calculate # 订单域-订单聚合-取消订单命令 myProjectName.cmd.order.order.cancel # 生产环境、租户abc下的定价费率更新命令 myProjectName.cmd.pricing.rate.update.prod.tenant-abc
对应的事件命名可以完全对齐层级,比如定价计算完成的事件就可以命名为myProjectName.evt.pricing.product-price.calculated,后续做观测、流配置的时候,直接用myProjectName.*.pricing.>就能匹配定价域所有进出的命令和事件,维护成本极低。
常见避坑点
- 绝对不要把订单ID、用户ID这类动态参数放在subject里,这类信息要放在消息体中,否则会导致JetStream的流、消费者元数据爆炸,性能急剧下降
- 不要把消息版本号放在subject里,版本信息放在消息头即可
- 全项目保持固定的层级数量,不要随意增减层级,避免通配符匹配出现漏匹配、错匹配
- 不要用过于宽泛的动作词,比如不要用
handle、process这类没有明确语义的动词,要看到动作段就知道命令要做什么
内容的提问来源于stack exchange,提问作者panza
相关产品推荐
相关产品推荐

