RocketMQ原理—2.源码设计简单分析一

大纲

1.NameServer的启动脚本

2.NameServer启动时会解析哪些配置

3.NameServer如何初始化Netty网络服务器

4.NameServer如何启动Netty网络服务器

5.Broker启动时是如何初始化配置的

6.BrokerController的创建以及包含的组件

7.BrokerController的初始化

8.BrokerController的启动

9.Broker如何把自己注册到NameServer上

10.BrokerOuterAPI是如何发送注册请求的

11.NameServer如何处理Broker的注册请求

12.Broker如何发送定时心跳的以及故障感知

1.NameServer的启动脚本

NameServer会通过rocketmq-master源码中distribution/bin目录下的mqnamesrv脚本来启动。在mqnamesrv脚本中,用于启动NameServer进程的命令如下。也就是使用sh命令执行runserver.sh脚本,然后通过这个脚本去启动NamesrvStartup这个Java类。

 

bash

代码解读

复制代码

sh ${ROCKETMQ_HOME}/bin/runserver.sh org.apache.rocketmq.namesrv.NamesrvStartup $@

在runserver.sh脚本中,启动NamesrvStartup这个Java类的命令如下:

 

ini

代码解读

复制代码

JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=320m" JAVA_OPT="${JAVA_OPT} -XX:+UseConcMarkSweepGC -XX:+UseCMSCompactAtFullCollection -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSClassUnloadingEnabled -XX:SurvivorRatio=8 -XX:-UseParNewGC" JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:${GC_LOG_DIR}/rmq_srv_gc_%p_%t.log -XX:+PrintGCDetails" JAVA_OPT="${JAVA_OPT} -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m" JAVA_OPT="${JAVA_OPT} -XX:-OmitStackTraceInFastThrow" JAVA_OPT="${JAVA_OPT} -XX:-UseLargePages" JAVA_OPT="${JAVA_OPT} -Djava.ext.dirs=${JAVA_HOME}/jre/lib/ext:${BASE_DIR}/lib" #JAVA_OPT="${JAVA_OPT} -Xdebug -Xrunjdwp:transport=dt_socket,address=9555,server=y,suspend=n" JAVA_OPT="${JAVA_OPT} ${JAVA_OPT_EXT}" JAVA_OPT="${JAVA_OPT} -cp ${CLASSPATH}" $JAVA ${JAVA_OPT} $@

可以看到,上述命令大致简化一下就是类似如下这样的一行命令:

 

vbscript

代码解读

复制代码

java -server -Xms4g -Xmx4g -Xmn2g org.apache.rocketmq.namesrv.NamesrvStartup

通过Java命令 + 一个有main()方法的NamesrvStartup类,就会启动一个JVM进程。这个JVM进程会执行NamesrvStartup类中的main()方法,从而完成启动NameServer需要的所有工作。

所以,启动NameServer的过程如下图示:

2.NameServer启动时会解析哪些配置

(1)什么是NamesrvController

(2)NamesrvController是如何被创建出来的

(3)NameServer的两个配置类

(4)NameServer两个配置类的解析

(5)完成NamesrvController组件的创建

(1)什么是NamesrvController

当执行NamesrvStartup的main()方法时,会执行NamesrvStartup的main0()方法:

 

typescript

代码解读

复制代码

//下面这个NamesrvStartup类,就是最为关键的NameServer进程的启动类 public class NamesrvStartup { ... //NameServer进程启动时,会执行NamesrvStartup类的main()方法 public static void main(String[] args) { main0(args); } public static NamesrvController main0(String[] args) { //NamesrvController是NameServer的核心代码组件 //NameServer一启动,就会去启动这个NamesrvController try { 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; } ... }

在上述源码中,有这么一行代码:

 

ini

代码解读

复制代码

NamesrvController controller = createNamesrvController(args);

这行代码就是在创建一个NamesrvController类,这个类是NameServer中的一个核心组件。由于NameServer需要接收Broker发送过来的要把自己注册到NameServer上的请求(因为知道有哪些Broker和管理Broker),以及需要接收客户端发送过来的从NameServer拉取元数据的请求(因为客户端需要知道一个Topic的MessageQueue都在哪些Broker上),所以才需要在NameServer中创建NamesrvController这个类专门用来接收Broker和客户端的网络请求。如下图示,NamesrvController组件是NameServer中的核心组件,用来负责接受网络请求的。

(2)NamesrvController是如何被创建出来的

NamesrvStartup的createNamesrvController()方法会创建出NamesrvController这个关键组件。

 

ini

代码解读

复制代码

public class NamesrvStartup { ... public static NamesrvController createNamesrvController(String[] args) throws IOException, JoranException { System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, Integer.toString(MQVersion.CURRENT_VERSION)); //PackageConflictDetect.detectFastjson(); Options options = ServerUtil.buildCommandlineOptions(new Options()); commandLine = ServerUtil.parseCmdLine("mqnamesrv", args, buildCommandlineOptions(options), new PosixParser()); if (null == commandLine) { System.exit(-1); return null; } 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(); } } if (commandLine.hasOption('p')) { InternalLogger console = InternalLoggerFactory.getLogger(LoggerName.NAMESRV_CONSOLE_NAME); MixAll.printObjectProperties(console, namesrvConfig); MixAll.printObjectProperties(console, nettyServerConfig); System.exit(0); } MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), namesrvConfig); if (null == namesrvConfig.getRocketmqHome()) { System.out.printf("Please set the %s variable in your environment to match the location of the RocketMQ installation%n", MixAll.ROCKETMQ_HOME_ENV); System.exit(-2); } LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); configurator.doConfigure(namesrvConfig.getRocketmqHome() + "/conf/logback_namesrv.xml"); log = InternalLoggerFactory.getLogger(LoggerName.NAMESRV_LOGGER_NAME); MixAll.printObjectProperties(log, namesrvConfig); MixAll.printObjectProperties(log, nettyServerConfig); final NamesrvController controller = new NamesrvController(namesrvConfig, nettyServerConfig); //remember all configs to prevent discard controller.getConfiguration().registerConfig(properties); return controller; } ... }

(3)NameServer的两个配置类


                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值