一、入口
public static void main(String[] args) {
main0(args);
}
public static NamesrvController main0(String[] args) {
try {
// 创建NamesrvController
NamesrvController controller = createNamesrvController(args);
start(controller);
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;
}
打开NameServer的启动类NamesrvStartup,如上面的代码所示,在main0方法中,NameServer主要是创建NamesrvController和启动NamesrvController两件事情,其中加载配置文件的过程就在createNamesrvController进行的。
二、加载配置文件
// 创建命令行对象,并指定命令行参数-c -h
Options options = ServerUtil.buildCommandlineOptions(new Options());
commandLine = ServerUtil.parseCmdLine("mqnamesrv", args, buildCommandlineOptions(options), new PosixParser());
if (null == commandLine) {
System.exit(-1);
return null;
在createNamesrvController方法中,首先创建了CommandLine对象,用于读取命令行参数,也就是程序运行参数,采用的是Apache CommandLi的工具包,这里采用的是PosixParser解析器,这里说明一下Apache CommandLi支持一下不同形式的参数:
- POSIX(Portable Operating System Interface of Unix)中的参数形式,例如 tar -zxvf foo.tar.gz
- GNU 中的长参数形式,例如 du --human-readable --max-depth=1
- Java 命令中的参数形式,例如 java -Djava.net.useSystemProxies=true Foo
- 短杠参数带参数值的参数形式,例如 gcc -O2 foo.c
- 长杠参数不带参数值的形式,例如 ant – projecthelp
代码中的PosixParser对应的就是POSIX参数格式。
public static Options buildCommandlineOptions(final Options options) {
Option opt = new Option("h", "help", false, "Print help");
opt.setRequired(false);
options.addOption(opt);
opt =
new Option("n", "namesrvAddr", true,
"Name server address list, eg: 192.168.0.1:9876;192.168.0.2:9876");
opt.setRequired(false);
options.addOption(opt);
return options;
}
public static Options buildCommandlineOptions(final Options options) {
Option opt = new Option("c", "configFile", true, "Name server config properties file");
opt.setRequired(false);
options.addOption(opt);
opt = new Option("p", "printConfigItem", false, "Print all config item");
opt.setRequired(false);
options.addOption(opt);
return options;
}
从代码来看,NameServer支持的命令行参数有:-h 、-n、 -c 、-p,通过Option类构造方法的参数可以看出不同参数的作用:
-h :打印帮助
-n:指定NameServer地址列表,例如: 192.168.0.1:9876;192.168.0.2:9876
-c:指定配置文件
-p:答应所有的配置项
final NamesrvConfig namesrvConfig = new NamesrvConfig();
final NettyServerConfig nettyServerConfig = new NettyServerConfig();
nettyServerConfig.setListenPort(9876);
if (commandLine.hasOption('c')) {
String file = commandLine.getOptionValue('c');
if (file != null) {
InputStream in = new BufferedInputStream(new FileInputStream(file));
properties = new Properties();
properties.load(in);
MixAll.properties2Object(properties, namesrvConfig);
MixAll.properties2Object(properties, nettyServerConfig);
namesrvConfig.setConfigStorePath(file);
System.out.printf("load config properties file OK, %s%n", file);
in.close();
}
}
NameServer通过-c参数加载配置文件,并把一份配置文件中的配置信息分为两类,分别是NameServer本身配置和Netty网关请求配置,对应NamesrvConfig和NettyServerConfig。
final NamesrvController controller = new NamesrvController(namesrvConfig, nettyServerConfig);
// remember all configs to prevent discard
controller.getConfiguration().registerConfig(properties);
通过配置文件获取到NamesrvConfig和NettyServerConfig配置信息之后,通过new NamesrvController的方式创建NamesrvController对象实例。
三、启动Netty
public static NamesrvController start(final NamesrvController controller) throws Exception {
if (null == controller) {
throw new IllegalArgumentException("NamesrvController is null");
}
boolean initResult = controller.initialize();
if (!initResult) {
controller.shutdown();
System.exit(-3);
}
Runtime.getRuntime().addShutdownHook(new ShutdownHookThread(log, new Callable<Void>() {
@Override
public Void call() throws Exception {
controller.shutdown();
return null;
}
}));
controller.start();
return controller;
}
在main0方法中,我们可以看到NameServer创建NamesrvController之后就是去start NamesrvController,在start方法中,主要是执行的是controller的初始化,调用的是controller.initialize方法,在这个方法里面最主要的是创建NettyRemotingServer对象,之后在controller.start方法中通过NettyRemotingServer start方法来启动Netty。
四、总结一下
NameServer启动的过程主要做了两件事情:
(1)通过-c 命令行参数加载配置文件,如果不指定则用默认配置。
(2)启动Netty。