前言
在前面的文章中,我们介绍了NameServer的源码,以及NameServer的底层启动流程等。对于Broker,它负责接收生产者发送的消息、持久化消息、提供消费者拉取消息的能力,并且通过心跳机制与 NameServer 保持通信,实现服务发现和负载均衡。
今天我们一起学习下Broker的启动流程以及底层源码!
Broker 在 RocketMQ 架构中的位置
Producer ——> Broker <—— Consumer
|
/
NameServer
Broker 是连接生产者、消费者和 NameServer 的桥梁,是消息流转的核心节点。
Broker 的启动流程
启动类入口:BrokerStartup
Broker 的启动类是 org.apache.rocketmq.broker.BrokerStartup
, main
方法是程序的入口。
public static void main(String[] args) {
// 解析命令行参数
Options options = ServerUtil.buildCommandlineOptions(new Options());
CommandLine commandLine = ...;
// 加载配置文件 broker.conf
final BrokerConfig brokerConfig = new BrokerConfig();
final NettyServerConfig nettyServerConfig = new NettyServerConfig();
final NettyClientConfig nettyClientConfig = new NettyClientConfig();
// 创建 BrokerController 实例
final BrokerController controller = createBrokerController(...);
// 初始化 BrokerController
controller.initialize();
// 启动 BrokerController
controller.start();
System.out.println("Broker 启动成功");
}
BrokerController
BrokerController
是 Broker 的“大脑”,负责管理所有模块的初始化与运行。
主要成员变量包括:
类型 | 说明 |
---|---|
BrokerConfig | 配置信息(比如 Broker 名称、IP、端口) |
NettyRemotingServer | 处理网络请求的服务器 |
MessageStore | 消息存储引擎,负责消息的读写 |
TopicConfigManager | 管理 Topic 配置 |
ConsumerOffsetManager | 管理消费者偏移量 |
ScheduledExecutorService | 定时任务调度器 |
Broker 的创建与初始化
创建 BrokerController
BrokerController controller = new BrokerController(brokerConfig, nettyServerConfig, nettyClientConfig);
构造函数只是简单赋值,真正的初始化其实发生在 initialize()
这个方法中。
初始化各模块
controller.initialize();
这个方法做了很多事,我们挑重点讲:
✅ 1. 初始化 Topic 相关管理器
this.topicConfigManager = new TopicConfigManager(this);
this.topicConfigManager.load(); // 加载 topic 配置
✅ 2. 初始化消费者偏移量管理器
this.consumerOffsetManager = new ConsumerOffsetManager(this);
this.consumerOffsetManager.load();
✅ 3. 初始化消息存储引擎
this.store = new DefaultMessageStore(this); // 默认使用磁盘存储
this.store.load(); // 加载已有的消息数据
✅ 4. 初始化网络通信组件
this.remotingServer = new NettyRemotingServer(nettyServerConfig, null);
this.remotingClient = new NettyRemotingClient(nettyClientConfig);
✅ 5. 注册处理器(Handler)
this.registerProcessor();
举个栗子:
- SendMessageProcessor:处理发送消息请求
- PullMessageProcessor:处理拉取消息请求
- HeartbeatProcessor:处理心跳包
Broker 如何向 NameServer 注册?
注册时机
Broker 在完成初始化后,会启动定时任务,定期向所有的 NameServer 发送心跳信息。
controller.start();
在 start()
方法中,会启动下面的定时任务:
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.registerBrokerAll(true, false, true);
} catch (Exception e) {
log.error("registerBrokerAll Exception", e);
}
}
}, 1000 * 10, 1000 * 30, TimeUnit.MILLISECONDS);
每 30 秒执行一次 registerBrokerAll
方法。
注册逻辑:registerBrokerAll
这个方法会构建一个包含当前 Broker 所有信息的对象 RegisterBrokerRequestHeader,并通过 Remoting 调用发送到所有 NameServer。
// 构建注册信息
RegisterBrokerRequestHeader requestHeader = new RegisterBrokerRequestHeader();
requestHeader.setBrokerAddr(addr);
requestHeader.setBrokerName(name);
requestHeader.setClusterName(clusterName);
// 发送到每个 NameServer
for (String namesrvAddr : nameServerAddressList) {
this.remotingClient.invokeSync(namesrvAddr, request, timeoutMillis);
}
NameServer 如何接受 Broker 的注册请求?
NameServer 的监听端口
NameServer 启动后会监听默认端口 9876
,等待 Broker 的注册请求。
请求处理器:ClusterNodeManager
当 NameServer 收到来自 Broker 的注册请求时,会由 ClusterNodeManager 处理。
public class ClusterNodeManager implements NettyRequestProcessor {
...
@Override
public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) {
switch (request.getCode()) {
case RequestCode.REGISTER_BROKER:
return registerBroker(ctx, request);
}
}
private RemotingCommand registerBroker(...) {
// 解析 Broker 注册信息
RegisterBrokerRequestHeader header = parseHeader(request);
// 存储 Broker 信息到 RouteInfoManager
routeInfoManager.registerBroker(
clusterName,
brokerName,
brokerAddr
);
return RemotingCommand.createResponseCommand(null);
}
}
存储结构:RouteInfoManager
RouteInfoManager是 NameServer 中管理路由信息的核心类,主要维护了以下关键数据结构:
- topicQueueTable: Topic 到队列的映射
- brokerAddrTable: Broker 名称到地址的映射
- clusterAddrTable: 集群名称到 Broker 列表的映射
- brokerLiveTable: 当前活跃的 Broker 连接信息
每次收到 Broker 心跳时,都会更新 brokerLiveTable 中的时间戳,用于判断 Broker 是否存活。
文章小结
如果上面的部分源码读取来毕竟烦,可以看下Broker 的核心流程总结:
Broker 启动
↓
加载配置 + 初始化模块(Topic、ConsumerOffset、Store等)
↓
启动 Netty 服务,监听请求
↓
定时向 NameServer 发送注册/心跳请求
↓
NameServer 接收请求,更新路由信息
本篇文章到这里就结束了,后续会继续分享RocketMQ相关的知识,感谢各位小伙伴们的支持!
希望这篇文章能帮助大家打开 RocketMQ Broker源码世界的大门!🚀