一、入口

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。

打赏
支付宝 微信
上一篇 下一篇