设计选择与取舍
本文解释当前架构如何划分职责,以及这些选择的成本。“已观察设计”概括现有代码和组件契约;理由部分是根据机制进行的工程解释,不宣称每项选择都有历史 ADR,也不宣称未经测量的性能收益已得到证明。
分离领域、协议和传输
已观察设计。 rocketmq-model 保存不依赖运行时的领域类型,rocketmq-protocol 负责请求/响应结构和编解码,rocketmq-transport 负责连接执行、帧 I/O 和传输预算。服务与客户端组合这些层,而非把全部行为放进一个 remoting crate。
解释与成本。 这种划分使消息/队列契约与 Tokio 连接生命周期分离,领域代码可以不打开套接字进行测试,但依赖更显式,原先通过 common/remoting 访问的导入需要迁移。类型跨 crate 移动并不意味着可以改变序列化含义。
修改共享类型时参阅模块地图、消息模型和协议/传输,避免传输便利 API 成为领域身份的第二个定义来源。
显式持有运行时
已观察设计。 顶层 RuntimeOwner 创建服务上下文,组件持有任务组和已接受后台工作;客户端接收运行时上下文及遥测句柄。关闭通过取消、等待、报告和截止时间完成。
解释与成本。 显式所有权使任务停止和资源释放责任可解释,但比构造函数静默创建运行时需要更多启动装配。库代码需要传递所需上下文,处理取消时不能假设远程写入会被撤销。
任务树与预算树不同,子上下文不自动获得独立配额。阻塞调用方超时不一定停止底层闭包,许可必须继续关联实际工作。参见运行时。
串行修改后发布不可变路由
已观察设计。 NameServer 通过路由所有者应用修改,发布逐主题不可变视图。会话/代际检查防止旧连接事件删除较新注册。普通 NameServer 不构成复制式 Raft 元数据集群。
解释与成本。 读者可以读取一致的主题快照,同时明确修改顺序,但这不提供跨全部主题事务,也不使独立部署的 NameServer 立即一致。Broker 注册和客户端刷新仍是必要收敛机制。
区分持久 KV 配置和临时路由注册,不将第二个 NameServer 描述为第一个的同步副本。参见 NameServer。
组合存储端口而不重新定义主数据持久性
已观察设计。 Store factory 选择一致的端口组合。在文档覆盖的组合中,本地 CommitLog 仍是主记录路径,ConsumeQueue 和索引是派生结构。RocksDB 派生后端不会将主日志替换为任意 RocksDB 数据库,分层存储属于独立次级路径。
解释与成本。 稳定主契约允许不同派生索引/查询选择,但恢复时必须将各游标与引擎和源纪元对齐。索引推进不代表更强复制或业务完成保证,修改 storeType 不能充当数据转换流程。
参见存储、存储后端和离线工具。将进度值用于恢复逻辑前,明确其来源。
分离写权限与副本进度
已观察设计。 Controller 模式 HA 使用显式 Broker 身份、主节点纪元和写权限/租约契约。同步副本集合进度具有自身含义,复制确认策略区分本地接受/持久化和要求的远程参与者。Rust Controller 使用 OpenRaft,而非 Java Controller 内部协议。
解释与成本。 副本数据追平不足以授权其接受写入。分离后可显式推理脑裂防护和故障切换,但除字节进度外,还需处理隔离、租约过期和成员状态。单成员“全部同步”条件不代表远程副本确认了数据。
不要仅凭功能名称相似就混合 Java/Rust Controller 成员或复用共识快照。参见 HA 与 Controller和兼容性。
在 Cluster 和 Local 后端之间共享 Proxy 契约
已观察设计。 Proxy Core 定义入口契约,Cluster 模式使用远程 RocketMQ 后端,Local 模式组合具有自身生命周期的嵌入式 Broker。二进制所选 feature 限制运行时可用模式。
解释与成本。 共享前端行为可支持不同部署单元,但 Local 模式改变进程所有权、存储和关闭责任。修改模式值不是透明迁移数据、会话或凭据的操作。入口传输成功仍需结合操作结果解释。
参见 Proxy 架构、部署和服务配置。排空任一模式时都应考虑活动会话和下游就绪状态。
分离观察与受控执行
已观察设计。 只读 MCP 使用读取适配器和受策略约束的观察路径,规划工具不执行变更。MCP Control 和 SRE 执行组件是独立产品,拥有各自凭据、操作注册及生命周期边界。普通 Dashboard 具有自身管理访问。
解释与成本。 可以部署诊断访问而不授予任意变更能力,执行则需要显式类型化集成。这带来独立配置和运维工作,不能通过将诊断工具接入更宽泛 Admin 会话来隐藏。模型生成建议不是执行权限。
分离不代表全部授权路径相同:MCP 指南记录了当前省略集群清单请求的限制。只有准确描述实际执行及例外,产品边界才有用。