快速开始指南:一键部署、状态验证与故障切换实践)
Apache RocketMQ 自动主从切换Controller 模式快速开始指南一键部署、状态验证与故障切换实践【免费下载链接】rocketmqApache RocketMQ is a cloud native messaging and streaming platform, making it simple to build event-driven applications.项目地址: https://gitcode.com/gh_mirrors/ro/rocketmq导读本文基于 Apache RocketMQ 仓库中的 docs/cn/controller/quick_start.md 展开完整讲解如何快速构建一套具备自动主从切换能力的 RocketMQ 集群从编译源码、一键启动到用mqadmin运维命令查看SyncStateSet与BrokerEpoch再到手动 Kill Master 验证故障切换全过程。读完本文你将掌握 ControllerDLedger 模式内嵌 NameServer、内嵌 3 节点集群、独立 3 节点集群三种部署形态的实操方法并能依据 deploy.md 与 design.md 进一步完成生产级新集群部署与旧集群升级。架构总览Controller 让“谁当 Master”不再靠人工在传统 RocketMQ 主从模式下Master 与 Slave 的角色由brokerId静态决定Master 故障时需要人工干预如修改配置、重启或依赖脚本切换可用性维护成本高。自动主从切换方案的核心是引入一个独立的Controller组件Controller 负责维护每个 broker 复制组broker-set的 SyncStateSet同步副本集合并基于多数派Quorum协议为集合内副本选举/指派 Master 与 Slave 角色当 Master 失联后Controller 会从 SyncStateSet 中自动选出新的 Master并将角色变更结果通知相关 Broker实现真正意义上的自动故障转移Controller 本身基于Raft 类协议DLedger组成集群从而自身具备高可用能力可以独立部署也可以内嵌在 NameServer 进程中通过enableControllerInNamesrv开关开启。该架构的详细设计思路见 设计思想新集群部署与旧集群升级的完整指南见 部署指南。编译 RocketMQ 源码在开始部署前需要先从源码构建发行包$ git clone https://github.com/apache/rocketmq.git $ cd rocketmq $ mvn -Prelease-all -DskipTests clean install -U构建成功后发行包会被输出到distribution/target/目录下内含bin/启动脚本与mqadmin运维工具与conf/各类配置文件后续所有操作都在发行包目录内完成。快速部署一条命令拉起“1 Controller 2 Broker”最小集群一键启动与停止进入发行包目录后直接运行快速启动脚本#{rocketmq-version} 替换为 rocketmq 实际版本号例如 5.0.0-SNAPSHOT $ cd distribution/target/rocketmq-{rocketmq-version}/rocketmq-{rocketmq-version}/ $ sh bin/controller/fast-try.sh start需要关闭快速集群时执行$ sh bin/controller/fast-try.sh stop从仓库中的脚本实现看fast-try.shdistribution/bin/controller/fast-try.sh实际做了以下事情startNameserver以-Xms512m -Xmx512m的 JVM 参数启动bin/mqnamesrv -c ./conf/controller/quick-start/namesrv.conf该配置开启了enableControllerInNamesrv true即 Controller 内嵌在 NameServer 中startBroker以-Xms1g -Xmx1g的 JVM 参数依次启动bin/mqbroker -c ./conf/controller/quick-start/broker-n0.conf和broker-n1.conf两个 BrokercheckConf启动前会校验三个配置文件是否齐全缺失即报错退出。也就是说快速部署默认会开启1 个内嵌了 Controller 的 NameServer 和 2 个 Broker。相关默认配置位于conf/controller/quick-start/目录即仓库中的 distribution/conf/controller/quick-start存储路径默认为/tmp/rmqstore。默认配置逐项解读namesrv.confdistribution/conf/controller/quick-start/namesrv.confenableControllerInNamesrv true controllerDLegerGroup group1 controllerDLegerPeers n0-127.0.0.1:9878 controllerDLegerSelfId n0配置项含义enableControllerInNamesrv是否将 Controller 以插件方式内嵌到 NameServer 进程中true表示开启controllerDLegerGroupController 所在的 DLedger Raft 组名称组内所有节点必须一致controllerDLegerPeersController 集群全部节点列表格式为selfId-ip:port多节点用;分隔controllerDLegerSelfId当前节点在 Controller 集群中的自 ID必须与controllerDLegerPeers中的某个selfId对应broker-n0.conf与broker-n1.confbroker-n0.conf / broker-n1.conf配置了两个属于同一 broker-setbrokerName broker-a的 Broker 节点端口与存储路径互不相同配置项broker-n0broker-n1含义brokerNamebroker-abroker-a同一复制组内所有副本必须同名brokerId-1-1-1表示由 Controller 动态分配 IDbrokerRoleSLAVESLAVE启动时均以 SLAVE 身份注册角色由 Controller 裁决enableControllerModetruetrue开启 Broker 的 Controller 模式接受 Controller 的角色管理controllerAddr127.0.0.1:9878127.0.0.1:9878Controller 地址快速部署中为内嵌 Controller 的 NameServer 地址namesrvAddr127.0.0.1:9876127.0.0.1:9876NameServer 地址allAckInSyncStateSettruetrue要求消息在 SyncStateSet 内全部副本确认后才返回成功是自动切换下保证数据一致性的关键listenPort3091130921Broker 对外服务端口storePathRootDir/storePathCommitLog/tmp/rmqstore/node00/tmp/rmqstore/node01各自独立的存储路径避免数据目录冲突提示brokerId -1是 Controller 模式下的典型写法——节点不再自行声明角色而是由 Controller 在注册与选举流程中动态分配 0Master或 1Slave等 ID。可对照 ControllerConfig.java 中controllerDLegerGroup、controllerDLegerPeers、controllerDLegerSelfId等字段了解其底层承载。验证 Controller 集群状态启动成功后用运维命令查看 Controller 元数据$ sh bin/mqadmin getControllerMetaData -a localhost:9878-a代表集群中任意一个 Controller 的地址。该命令对应仓库中的 GetControllerMetaDataSubCommand.java会返回 Controller 组的 Leader 信息与全部 Peer 列表。至此集群启动成功即可向集群收发消息并进行下面的切换测试。查看 SyncStateSet 与 BrokerEpoch查看 SyncStateSetSyncStateSet同步副本集合记录了当前与 Master 保持同步的副本集合是 Controller 决策切换的重要依据可以通过运维工具查看$ sh bin/mqadmin getSyncStateSet -a localhost:9878 -b broker-a-a是任意一个 Controller 的地址-b是目标 broker-set 名称。命令实现在 GetSyncStateSetSubCommand.java。如果顺利的话可以看到类似下图的内容集合内包含当前 Master 与同步中的 Slave 副本信息查看 BrokerEpochBrokerEpoch 用于标记每一次 Master 选举的代数防止旧 Master 复活后产生“双主”脑裂可通过运维工具查看$ sh bin/mqadmin getBrokerEpoch -n localhost:9876 -b broker-a-n代表任意一个 NameServer 的地址。命令实现在 GetBrokerEpochSubCommand.java。如果顺利的话可以看到类似下图的内容包含 epoch 代数与 master/slave 的 brokerId 记录切换验证Kill 掉 Master观察自动故障转移集群部署成功后即可手动验证自动主从切换能力。步骤一定位并 Kill 原 Master在上文的快速部署中两个 Broker 的端口分别为 30911broker-n0与 30921broker-n1其中被 Controller 选为 Master 的是使用端口30911的进程。通过进程过滤命令找到并杀掉它# 查找端口: $ ps -ef|grep java|grep BrokerStartup|grep ./conf/controller/quick-start/broker-n0.conf|grep -v grep|awk {print $2} # 杀掉 master: $ kill -9 PID说明fast-try.sh的stopBroker实现见 distribution/bin/controller/fast-try.sh也使用了类似的ps -ef | grep BrokerStartup | grep conf | grep -v grep | awk {print $2}模式来按配置定位进程这里为模拟真实故障直接使用kill -9。步骤二观察 Master 是否切换杀掉 Master 后再次查看 SyncStateSet$ sh bin/mqadmin getSyncStateSet -a localhost:9878 -b broker-a可以发现Master 已经发生了切换——Controller 感知到原 Master 失联scanNotActiveBrokerInterval默认为 5 秒扫描一次见 ControllerConfig.java从 SyncStateSet 中选出新的 Master 并完成角色通知整个过程无需人工干预这即是 Controller 模式相对传统主从模式的核心价值。Controller 内嵌 NameServer 集群部署3 节点对于生产环境Controller 需要以多副本集群方式部署以保障自身高可用。第一种形态是Controller 以插件方式内嵌于 NameServer 集群3 个 Node。一键启动$ sh bin/controller/fast-try-namesrv-plugin.sh start该脚本fast-try-namesrv-plugin.sh会依次启动三个 NameServer内嵌 Controller$ nohup bin/mqnamesrv -c ./conf/controller/cluster-3n-namesrv-plugin/namesrv-n0.conf $ nohup bin/mqnamesrv -c ./conf/controller/cluster-3n-namesrv-plugin/namesrv-n1.conf $ nohup bin/mqnamesrv -c ./conf/controller/cluster-3n-namesrv-plugin/namesrv-n2.conf 三个节点的配置位于 distribution/conf/controller/cluster-3n-namesrv-plugin以namesrv-n0.conf为例# Namesrv config listenPort 9876 enableControllerInNamesrv true # controller config controllerDLegerGroup group1 controllerDLegerPeers n0-127.0.0.1:9878;n1-127.0.0.1:9868;n2-127.0.0.1:9858 controllerDLegerSelfId n0其余两节点n1、n2仅listenPort9886/9896与controllerDLegerSelfIdn1/n2不同controllerDLegerPeers必须三节点完全一致以组成同一个 DLedger Raft 组。验证 Controller 集群状态$ sh bin/mqadmin getControllerMetaData -a localhost:9878-a是任意一个 Controller 的地址。如果 Controller 启动成功可以看到类似以下内容#ControllerGroup group1 #ControllerLeaderId n0 #ControllerLeaderAddress 127.0.0.1:9878 #Peer: n0:127.0.0.1:9878 #Peer: n1:127.0.0.1:9868 #Peer: n2:127.0.0.1:9858接入 Broker 与停止集群启动成功后Broker 以 Controller 模式部署enableControllerMode true、controllerAddr指向任一 Controller 地址即可使用该 Controller 集群。需要快速停止集群时$ sh bin/controller/fast-try-namesrv-plugin.sh stop使用fast-try-namesrv-plugin.sh脚本快速部署默认配置在conf/controller/cluster-3n-namesrv-plugin里面并且会启动3 个 NameServer 和 3 个 Controller内嵌于 NameServer。Controller 独立集群部署3 节点第二种形态是Controller 独立部署与 NameServer 完全解耦适合已有 NameServer 集群、仅需新增 Controller 能力的场景。一键启动$ sh bin/controller/fast-try-independent-deployment.sh start该脚本fast-try-independent-deployment.sh会启动三个独立 Controller 进程$ nohup bin/mqcontroller -c ./conf/controller/cluster-3n-independent/controller-n0.conf $ nohup bin/mqcontroller -c ./conf/controller/cluster-3n-independent/controller-n1.conf $ nohup bin/mqcontroller -c ./conf/controller/cluster-3n-independent/controller-n2.conf 三个节点的配置位于 distribution/conf/controller/cluster-3n-independent以controller-n0.conf为例controllerDLegerGroup group1 controllerDLegerPeers n0-127.0.0.1:9878;n1-127.0.0.1:9868;n2-127.0.0.1:9858 controllerDLegerSelfId n0mqcontroller启动入口对应仓库中的 ControllerStartup.java独立模式不再需要enableControllerInNamesrv与 NameServer 的listenPort仅需配置 DLedger 组信息。验证 Controller 集群状态$ sh bin/mqadmin getControllerMetaData -a localhost:9878如果 Controller 启动成功可以看到类似以下内容注意本例中 Leader 为 n1说明 Leader 由 Raft 选举动态产生不一定是 n0#ControllerGroup group1 #ControllerLeaderId n1 #ControllerLeaderAddress 127.0.0.1:9868 #Peer: n0:127.0.0.1:9878 #Peer: n1:127.0.0.1:9868 #Peer: n2:127.0.0.1:9858接入 Broker 与停止集群启动成功后Broker 以 Controller 模式部署即可使用该 Controller 集群。需要快速停止集群时$ sh bin/controller/fast-try-independent-deployment.sh stop使用fast-try-independent-deployment.sh脚本快速部署默认配置在conf/controller/cluster-3n-independent里面并且会启动3 个独立部署的 Controller 组成一个集群。三种部署形态对比与选型建议部署形态启动命令进程数配置文件目录适用场景快速部署内嵌单点fast-try.sh start1 NameServer含 Controller 2 Brokerdistribution/conf/controller/quick-start本地体验、功能验证、开发调试Controller 内嵌 NameServer 集群fast-try-namesrv-plugin.sh start3 NameServer各含 Controllerdistribution/conf/controller/cluster-3n-namesrv-plugin希望复用 NameServer 进程、减少部署组件数的生产场景Controller 独立集群fast-try-independent-deployment.sh start3 Controllerdistribution/conf/controller/cluster-3n-independent已有 NameServer 集群、Controller 独立扩缩容的生产场景三种形态下Broker 侧的接入方式完全一致设置enableControllerMode true、controllerAddr 任一Controller地址并将brokerId设为-1交由 Controller 动态分配。注意事项与最佳实践Controller 高可用需要三副本及以上若需要保证 Controller 具备容错能力Controller 部署需要三副本及以上遵循 Raft 的多数派协议容忍少数节点故障单副本 Controller 无法在自身故障时继续提供仲裁能力。多机部署时务必修改controllerDLegerPeers中的 IP配置参数controllerDLegerPeers中的 IP 地址需要配置成其他节点能够访问的 IP在多机器部署的时候尤为重要。仓库提供的示例127.0.0.1仅供单机快速体验参考实际部署需根据环境修改调整。allAckInSyncStateSet与数据一致性快速部署配置中开启了allAckInSyncStateSettrue要求消息被 SyncStateSet 内全部副本确认后才返回成功这是保证 Master 切换后不丢消息的关键设置生产环境可根据容灾与延迟要求权衡。关注不可用 Master 的选举策略从 ControllerConfig.java 的源码可以看出Controller 还支持enableElectUncleanMaster是否允许选举不在 SyncStateSet 中的 Master默认false、electMasterMaxRetryCount选举失败最大重试次数默认 3等高级参数生产调优时可结合 设计思想 与 部署指南 综合评估。总结本文从零完成了 RocketMQ 自动主从切换集群的快速构建与验证通过fast-try.sh一条命令拉起最小集群用getControllerMetaData、getSyncStateSet、getBrokerEpoch三个运维命令确认 Controller 与复制组状态并通过 Kill Master 实测了自动切换能力随后给出内嵌 NameServer 与独立部署两种 3 节点生产形态的部署方法。基于这套快速开始流程配合仓库中的 deploy.md新集群部署与旧集群升级与 design.md架构与选举设计即可将自动主从切换方案落地到实际生产环境。【免费下载链接】rocketmqApache RocketMQ is a cloud native messaging and streaming platform, making it simple to build event-driven applications.项目地址: https://gitcode.com/gh_mirrors/ro/rocketmq创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考