前言
上一篇讲到使用命令行启动namesrv时,最终会以NamesrvStartup
作为为启动类,所以这篇主要来记录一下NamesrvStartup
的源码分析。分析的RocketMQ的版本是4.3.1
。
NamesrvStartup
首先我觉得在看源码的时候,需要把握住一个类的大概流程,而不是看到一个功能块就deep进去。首先要明白namesrv是用来做什么的,简单的来考虑就是一个提供了通信功能可以与生产者、消费者、broker进行交互,然后能有一些队列可以保存broker注册进来的broker消息,可以保存生产者的消息等。按照这个思路往下看具体的代码。
所以我先简单的阐述一下NamesrvStartup.java
这个类的具体流程。下面的图中篮框就是NamesrvStartup
主要做的工作。
简单流程的描述就是先根据配置文件和命令行参数生成实例化nettyConfig
/namesrvConfig
对象,然后根据这两个对象生成NamesrvController
,然后调用返回对象中的initialize()方法,将通信模块的组件初始化,最后调用start()方法将netty服务启动。
1.进入main0()
下面是NamesrvStartup的入口main,可以看到调用了main0接口。
1 | public static void main(String[] args) { |
main0主要工作也比较明了,第一,就是根据命令行传入的参数实例化了一个NamesrvController
。NamesrvController
就是控制nameServer的一个类,包含了服务启动配置、通信模块配置、键值对的存储等等。第二,start(controller)主要是将netty服务启动起来。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public static NamesrvController main0(String[] args) {
try {
NamesrvController controller = createNamesrvController(args); // 在里面初始化了namesrv和netty,就是设置了它们的参数
start(controller); //主要是启动了一个netty服务用来监听
String tip = "The Name Server boot success. serializeType=" + RemotingCommand.getSerializeTypeConfigInThisServer();
log.info(tip);
System.out.printf("%s%n", tip);
return controller;
} catch (Throwable e) {
e.printStackTrace();
System.exit(-1);
}
return null;
}
2.进入createNamesrvController
根据前面的描述知道,createNamesrvController这个类首先会获取启动时的参数,然后将参数都保留在了NamesrvConfig
和NettyServerConfig
对象中。截取部分createNamesrvController中的代码:
1 | //用来解析命令行中的参数args,保留在commandLIne中,new Option("h","help",false,"print help"); |
经过上面的代码,可以得到一个对象保留了namesrv的配置,另外一个保存了nettyServer的配置,然后利用这两个配置对象生成一个NamesrvController,然后把对象返回到main0方法中。截取部分createNamesrvController中的代码:
1 | final NamesrvController controller = new NamesrvController(namesrvConfig, nettyServerConfig); //创建了一个NamesrvController,根据配置文件 |
为了能够清楚的将明白,NamesrvController构造函数这里就先不deep。
3.进入start(controller)
前面的步骤得到了一个NamesrvController对象,它不仅有服务运行相关的配置,还有很多List来存放各种消息(NamesrvController构造函数可以知道)。现在往事具备了,就把这个服务启动起来吧。下面是start(controller)的代码:
1 | public static NamesrvController start(final NamesrvController controller) throws Exception { |
主要是两个事情,第一调用了initialize(),第二就是start()了。
initialize()就是根据nettyServerConfig中的配置初始化了netty服务,主要是定义RequestCode,用来作为netty的通信协议字段,初始化线程池,初始化通信层,增加定时任务等。initialize代码:
1 | public boolean initialize() { |
start()就是启动了netty服务:
1 | public void start() throws Exception { |