Broker在RocketMQ中就相当于消息仓库,负责对消息的存储、管理和支配,并一直为生产者和消费者提供服务,那么Broker就得提前创建和启动了,本章内容就是剖析其过程。
5.1 创建
创建brokerControker主要做了以下几件事:
1.创建并设置rocketmq作为命令行执行时的选项操作
2.创建并设置broker作为服务端和客户端的Netty信息:缓冲区大小、端口等
3.解析命令行执行时-c 参数对应的properties文件内容,并覆盖系统默认设置的属性信息
4.调用controller.initialize()初始化方法,对controller做初始化工作
5.添加系统关闭时的钩子操作,主要是对controller资源的释放,调用controller.shutdown()方法
注:代码中只包含主要代码,一些不重要的代码删除了,减少篇幅的占用
public static BrokerController createBrokerController(String[] args) {
//设置当前broker的版本信息
System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, Integer.toString(MQVersion.CURRENT_VERSION));
//默认设置socket发送消息缓冲区大小为131072字节(128K)
if (null == System.getProperty(NettySystemConfig.COM_ROCKETMQ_REMOTING_SOCKET_SNDBUF_SIZE)) {
NettySystemConfig.socketSndbufSize = 131072;
}
//默认设置socket接收消息缓冲区大小为131072字节(128K)
if (null == System.getProperty(NettySystemConfig.COM_ROCKETMQ_REMOTING_SOCKET_RCVBUF_SIZE)) {
NettySystemConfig.socketRcvbufSize = 131072;
}
try {
//PackageConflictDetect.detectFastjson();
//生成命令行参数选项,比如命令行中输入mqbroker -help,就可以看到这些选项
Options options = ServerUtil.buildCommandlineOptions(new Options());
commandLine = ServerUtil.parseCmdLine("mqbroker", args, buildCommandlineOptions(options),
new PosixParser());
if (null == commandLine) {
System.exit(-1);
}
//创建brokerConfig的整体配置对象,包括rocketmq文件存储主目录、namesrv地址,ip、name、brokerId等
final BrokerConfig brokerConfig = new BrokerConfig();
//broker提供的netty服务端的配置
final NettyServerConfig nettyServerConfig = new NettyServerConfig();
//broker提供的netty客户端的配置,因为broker要作为客户端连接到namesrv,所以需要客户端这么一个角色
final NettyClientConfig nettyClientConfig = new NettyClientConfig();
//设置是否走tls安全传输协议的标识
nettyClientConfig.setUseTLS(Boolean.parseBoolean(System.getProperty(TLS_ENABLE,
String.valueOf(TlsSystemConfig.tlsMode == TlsMode.ENFORCING))));
//设置默认服务端监听端口,这个可以通过配置文件自己设定
nettyServerConfig.setListenPort(10911);
//消息存储相关配置(包含存放路径、commitLog单个文件大小【1G】、consumeQueue单个文件大小【6M】、commitLog文件刷盘时间间隔【500ms】等)
final MessageStoreConfig messageStoreConfig = new MessageStoreConfig();
if (BrokerRole.SLAVE == messageStoreConfig.getBrokerRole()) {
// 如果是从节点,需要将 accessMessageInMemorymaxRatio(访问消息在内存中的比率) 设置成比默认(40)小10,也就是30,这个知识点,在后续也会细讲
int ratio = messageStoreConfig.getAccessMessageInMemoryMaxRatio() - 10;
messageStoreConfig.setAccessMessageInMemoryMaxRatio(ratio);
}
//解析命令行启动行用户设置的properties文件,并覆盖系统设置的属性内容
if (commandLine.hasOption('c')) {
String file = commandLine.getOptionValue('c');
if (file != null) {
configFile = file;
InputStream in = new BufferedInputStream(new FileInputStream(file));
properties = new Properties();
properties.load(in);
properties2SystemEnv(properties);
MixAll.properties2Object(properties, brokerConfig);
MixAll.properties2Object(properties, nettyServerConfig);
MixAll.properties2Object(properties, nettyClientConfig);
MixAll.properties2Object(properties, messageStoreConfig);
BrokerPathConfigHelper.setBrokerConfigPath(file);
in.close();
}
}
MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), brokerConfig);
//rocketmqHome主目录必须配置,要么从属性文件中配置{rocketmq.home.dir}属性,要么设置ROCKETMQ_HOME环境变量
if (null == brokerConfig.getRocketmqHome()) {
System.out.printf("Please set the %s variable in your environment to match the location of the RocketMQ installation", MixAll.ROCKETMQ_HOME_ENV);
System.exit(-2);
}
//namesrAddr也是必须设置的项,虽然没有设置系统会自己按着规则去找,但是不建议,还是自己设置
String namesrvAddr = brokerConfig.getNamesrvAddr();
if (null != namesrvAddr) {
try {
// 多个namesrv地址以;分隔
String[] addrArray = namesrvAddr.split(";");
for (String addr : addrArray) {
// 遍历namesrv地址,创建InetSocketAddress
RemotingUtil.string2SocketAddress(addr);
}
} catch (Exception e) {
System.out.printf(
"The Name Server Address[%s] illegal, please set it as follows, \"127.0.0.1:9876;192.168.0.1:9876\"%n",
namesrvAddr);
System.exit(-3);
}
}
switch (messageStoreConfig.getBrokerRole()) {
case ASYNC_MASTER:
case SYNC_MASTER:
//主broker需要设置brokerId=0
brokerConfig.setBrokerId(MixAll.MASTER_ID);
break;
case SLAVE:
//从broker的brokerId必须大于0
if (brokerConfig.getBrokerId() <= 0) {
System.out.printf("Slave's brokerId must be > 0");
System.exit(-3);
}
break;
default:
break;
}
//设置主从复制时主broker监听从broker主动发起数据拉取时的netty监听端口
messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);
//日志打印设置
LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
JoranConfigurator configurator = new JoranConfigurator();
configurator.setContext(lc);
lc.reset();
configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/logback_broker.xml");
// 处理选项参数
if (commandLine.hasOption('p')) {
InternalLogger console = InternalLoggerFactory.getLogger(LoggerName.BROKER_CONSOLE_NAME);
MixAll.printObjectProperties(console, brokerConfig);
MixAll.printObjectProperties(console, nettyServerConfig);
MixAll.printObjectProperties(console, nettyClientConfig);
MixAll.printObjectProperties(console, messageStoreConfig);
System.exit(0);
} else if (commandLine.hasOption('m')) {
InternalLogger console = InternalLoggerFactory.getLogger(LoggerName.BROKER_CONSOLE_NAME);
MixAll.printObjectProperties(console, brokerConfig, true);
MixAll.printObjectProperties(console, nettyServerConfig, true);
MixAll.printObjectProperties(console, nettyClientConfig, true);
MixAll.printObjectProperties(console, messageStoreConfig, true);
System.exit(0);
}
log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
MixAll.printObjectProperties(log, brokerConfig);
MixAll.printObjectProperties(log, nettyServerConfig);
MixAll.printObjectProperties(log, nettyClientConfig);
MixAll.printObjectProperties(log, messageStoreConfig);
//创建BrokerController,这个构造函数中创建的内容太多了,一起放到controller.initialize()里讲
final BrokerController controller = new BrokerController(
brokerConfig,
nettyServerConfig,
nettyClientConfig,
messageStoreConfig);
// remember all configs to prevent discard
controller.getConfiguration().registerConfig(properties);
//初始化
boolean initResult = controller.initialize();
if (!initResult) {
controller.shutdown(); //初始化失败,就关闭
System.exit(-3);
}
//添加系统关闭时的钩子操作,主要是对controller资源的释放,调用controller.shutdown()方法
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
private volatile boolean hasShutdown = false;
private AtomicInteger shutdownTimes = new AtomicInteger(0);
@Override
public void run() {
synchronized (this) {
log.info("Shutdown hook was invoked, {}", this.shutdownTimes.incrementAndGet());
if (!this.hasShutdown) {
this.hasShutdown = true;
long beginTime = System.currentTimeMillis();
controller.shutdown();
long consumingTimeTotal = System.currentTimeMillis() - beginTime;
log.info("Shutdown hook over, consuming total time(ms): {}", consumingTimeTotal);
}
}
}
}, "ShutdownHook"));
return controller;
} catch (Throwable e) {
e.printStackTrace();
System.exit(-1);
}
return null;
}
BrokerController构造函数
构造函数里面,就是对Broker要使用的内容创建对象并赋值,关于这些内容的具体使用,在初始化及后续执行过程中都会有讲解,所以现阶段先不要纠结它们是什么,大概有个概念,混个脸熟就行。
public BrokerController(
final BrokerConfig brokerConfig,
final NettyServerConfig nettyServerConfig,
final NettyClientConfig nettyClientConfig,
final MessageStoreConfig messageStoreConfig
) {
// broker的配置存放对象
this.brokerConfig = brokerConfig;
// netty服务端配置(broker作为服务端为生产者和消费者提供服务)
this.nettyServerConfig = nettyServerConfig;
// netty客户端配置(broker作为客户端与name server沟通)
this.nettyClientConfig = nettyClientConfig;
// 消息存储配置对象
this.messageStoreConfig = messageStoreConfig;
// 管理消息者索引的对象
this.consumerOffsetManager = new ConsumerOffsetManager(this);
// topic配置管理对象
this.topicConfigManager = new TopicConfigManager(this);
// 消息拉取处理器
this.pullMessageProcessor = new PullMessageProcessor(this);
// 处理消费端拉取消息时hold住的请求服务,这是一个线程任务对象
this.pullRequestHoldService = new PullRequestHoldService(this);
// 消息到达监听器
this.messageArrivingListener = new NotifyMessageArrivingListener(this.pullRequestHoldService);
// 消费者id变更监听器
this.consumerIdsChangeListener = new DefaultConsumerIdsChangeListener(this);
// 消费者管理器
this.consumerManager = new ConsumerManager(this.consumerIdsChangeListener);
// 消费者过滤管理器,里面涉及布容过滤器
this.consumerFilterManager = new ConsumerFilterManager(this);
// 生产者管理器
this.producerManager = new ProducerManager();
//客户端总管服务,启动broker总管服务线程,每10秒扫描一次客户端(发送、消费、查询)连接,将长期(默认2分钟)未激活(其实就是没心跳了)的通道关闭
this.clientHousekeepingService = new ClientHousekeepingService(this);
this.broker2Client = new Broker2Client(this);
// 订阅组管理器
this.subscriptionGroupManager = new SubscriptionGroupManager(this);
// broker 对外 api,封装broker作为客户端与namesrv的交互服务
this.brokerOuterAPI = new BrokerOuterAPI(nettyClientConfig);
this.filterServerManager = new FilterServerManager(this);
// 从节点同步器
this.slaveSynchronize = new SlaveSynchronize(this);
// 下面这部分是针对不同交互内容创建的任务队列
// 发送请求
this.sendThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getSendThreadPoolQueueCapacity());
// 拉取请求
this.pullThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getPullThreadPoolQueueCapacity());
// 查询请求
this.queryThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getQueryThreadPoolQueueCapacity());
// 客户端管理
this.clientManagerThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getClientManagerThreadPoolQueueCapacity());
// 消费者管理
this.consumerManagerThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getConsumerManagerThreadPoolQueueCapacity());
// 心跳请求
this.heartbeatThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getHeartbeatThreadPoolQueueCapacity());
// 结束事务请求
this.endTransactionThreadPoolQueue = new LinkedBlockingQueue<Runnable>(this.brokerConfig.getEndTransactionPoolQueueCapacity());
// broker 状态管理
this.brokerStatsManager = new BrokerStatsManager(this.brokerConfig.getBrokerClusterName());
this.setStoreHost(new InetSocketAddress(this.getBrokerConfig().getBrokerIP1(), this.getNettyServerConfig().getListenPort()));
// broker 快速失败对象
this.brokerFastFailure = new BrokerFastFailure(this);
// 统一包装配置对象
this.configuration = new Configuration(
log,
BrokerPathConfigHelper.getBrokerConfigPath(),
this.brokerConfig, this.nettyServerConfig, this.nettyClientConfig, this.messageStoreConfig
);
}
BrokerController.initialize 初始化
public boolean initialize() throws CloneNotSupportedException {
/*以下4步操作,分别是加载topic.json、consumerOffset.json、subscriptionGroup.json、consumerFilter.json这4个文件的内容并做解析,这些文件的存放路径,见6.3 BrokerPathConfigHelper类,
下面主要介绍下这几个文件内部存放的是什么内容,做什么用:
1.topic.json:存储的是该broker支持的所有topic信息,对应类TopicConfigSerializeWrapper,每个topic对应一个TopicConfig,内部包含topic支持读写队列数、topicName、读写权限(perm)、是否顺序
2.consumerOffset.json:存储的是每个消费者组下的topic的每个cp的消费偏移,对应类ConsumerOffsetManager,内部维护一个ConcurrentMap<String, ConcurrentMap<Integer, Long>>
key=topic@group({topicName}@{consumerGroup})
value=每个queueId对应的偏移
3.subscriptionGroup.json:存储的是订阅组信息,对应SubscriptionGroupManager类,内部维护一个ConcurrentMap<String, SubscriptionGroupConfig>
key=group(消费者组)
value=SubscriptionGroupConfig
4.consumerFilter.json:存储的是消费者过滤数据信息,对应ConsumerFilterManager类,内部维护一个ConcurrentMap<String, FilterDataMapByTopic>,其实就是对应消费者设置的tags
key=topic
value=FilterDataMapByTopic
*/
boolean result = this.topicConfigManager.load();
result = result && this.consumerOffsetManager.load();
result = result && this.subscriptionGroupManager.load();
result = result && this.consumerFilterManager.load();
//加载都成功,继续执行,result只要有一个为false,那就是false,后续操作就不会执行了,则初始化失败
if (result) {
try {
//创建消息存储操作类,这个类包含对commitlog、consumerqueue、index文件的直接或间接的存储操作
this.messageStore =
new DefaultMessageStore(this.messageStoreConfig, this.brokerStatsManager, this.messageArrivingListener,
this.brokerConfig);
//DLedger开启时才会调用,DLedger后续专题介绍,本次版本不做过多介绍
if (messageStoreConfig.isEnableDLegerCommitLog()) {
DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore);
((DLedgerCommitLog)((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
}
// broker 状态对象
this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore);
//加载messageStore插件,如果有,那么生成新的messageStore对象替换DefaultMessageStore,这个是可以使用者配置的,实现逻辑是通过反射来操作
MessageStorePluginContext context = new MessageStorePluginContext(messageStoreConfig, brokerStatsManager, messageArrivingListener, brokerConfig);
this.messageStore = MessageStoreFactory.build(context, this.messageStore);
//构建布隆过滤器,加速SQL92过滤效率,避免每次解析sql,rocketmq对消息的过滤有2种方式,TAG和SQL,使用SQL过滤时就可以用这个布隆过滤器
this.messageStore.getDispatcherList().addFirst(new CommitLogDispatcherCalcBitMap(this.brokerConfig, this.consumerFilterManager));
} catch (IOException e) {
result = false;
log.error("Failed to initialize", e);
}
}
//加载commitlog/cq/indexFile三个文件信息到内存
result = result && this.messageStore.load();
if (result) {
//broker服务端Netty,主要负责接收生产者和消费者对broker发起消息:发送、消费等
this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.clientHousekeepingService);
NettyServerConfig fastConfig = (NettyServerConfig) this.nettyServerConfig.clone();
fastConfig.setListenPort(nettyServerConfig.getListenPort() - 2);
this.fastRemotingServer = new NettyRemotingServer(fastConfig, this.clientHousekeepingService);
//创建消息发送处理线程池,默认线程数为1
this.sendMessageExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getSendMessageThreadPoolNums(),
this.brokerConfig.getSendMessageThreadPoolNums(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.sendThreadPoolQueue,
new ThreadFactoryImpl("SendMessageThread_"));
//创建消息拉取处理线程池,默认线程数16 + cpu核数 * 2;
this.pullMessageExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getPullMessageThreadPoolNums(),
this.brokerConfig.getPullMessageThreadPoolNums(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.pullThreadPoolQueue,
new ThreadFactoryImpl("PullMessageThread_"));
//创建消息查询处理线程池,默认线程数8 + cpu核数 * 2;
this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getQueryMessageThreadPoolNums(),
this.brokerConfig.getQueryMessageThreadPoolNums(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.queryThreadPoolQueue,
new ThreadFactoryImpl("QueryMessageThread_"));
this.adminBrokerExecutor =
Executors.newFixedThreadPool(this.brokerConfig.getAdminBrokerThreadPoolNums(), new ThreadFactoryImpl(
"AdminBrokerThread_"));
//客户端管理线程池
this.clientManageExecutor = new ThreadPoolExecutor(
this.brokerConfig.getClientManageThreadPoolNums(),
this.brokerConfig.getClientManageThreadPoolNums(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.clientManagerThreadPoolQueue,
new ThreadFactoryImpl("ClientManageThread_"));
//心跳处理线程池
this.heartbeatExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getHeartbeatThreadPoolNums(),
this.brokerConfig.getHeartbeatThreadPoolNums(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.heartbeatThreadPoolQueue,
new ThreadFactoryImpl("HeartbeatThread_", true));
//结束事务处理线程池
this.endTransactionExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getEndTransactionThreadPoolNums(),
this.brokerConfig.getEndTransactionThreadPoolNums(),
1000 * 60,
TimeUnit.MILLISECONDS,
this.endTransactionThreadPoolQueue,
new ThreadFactoryImpl("EndTransactionThread_"));
//消费者客户端管理
this.consumerManageExecutor =
Executors.newFixedThreadPool(this.brokerConfig.getConsumerManageThreadPoolNums(), new ThreadFactoryImpl(
"ConsumerManageThread_"));
//给各netty服务端注册请求处理器和对应的线程池
this.registerProcessor();
//当前时间距离明天早上零点的时间戳
final long initialDelay = UtilAll.computNextMorningTimeMillis() - System.currentTimeMillis();
//间隔时间24小时
final long period = 1000 * 60 * 60 * 24;
//启动定时任务,每天记录一次rocketmq运行状态,主要统计每天发送消息和拉取消息数
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.getBrokerStats().record();
} catch (Throwable e) {
log.error("schedule record error.", e);
}
}
}, initialDelay, period, TimeUnit.MILLISECONDS);
//定时任务,每5秒(默认)持久化一次消费偏移值到文件consumerOffset.json
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.consumerOffsetManager.persist();
} catch (Throwable e) {
log.error("schedule persist consumerOffset error.", e);
}
}
}, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS);
//定时任务,每5秒(默认)持久化一次消费偏移值到文件consumerOffset.json
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.consumerFilterManager.persist();
} catch (Throwable e) {
log.error("schedule persist consumer filter error.", e);
}
}
}, 1000 * 10, 1000 * 10, TimeUnit.MILLISECONDS);
//启动broker保护线程池,每3分钟执行一次,当消费者来消费的偏移与当前commitlog最大偏移值相差16G(默认)时,拒绝为该消费者组提供服务
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.protectBroker();
} catch (Throwable e) {
log.error("protectBroker error.", e);
}
}
}, 3, 3, TimeUnit.MINUTES);
//启动打印水印(发送消息数、拉取消息数、查询消息数、事务查询数)线程,每秒执行1次
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.printWaterMark();
} catch (Throwable e) {
log.error("printWaterMark error.", e);
}
}
}, 10, 1, TimeUnit.SECONDS);
//启动每分钟执行一次打印commitlog偏移与cq/indexFile偏移之差的线程池
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
log.info("dispatch behind commit log {} bytes", BrokerController.this.getMessageStore().dispatchBehindBytes());
} catch (Throwable e) {
log.error("schedule dispatchBehindBytes error.", e);
}
}
}, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
//将最新的namesrv地址信息更新到内存中
if (this.brokerConfig.getNamesrvAddr() != null) {
this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr());
log.info("Set user specified name server address: {}", this.brokerConfig.getNamesrvAddr());
} else if (this.brokerConfig.isFetchNamesrvAddrByAddressServer()) {
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.brokerOuterAPI.fetchNameServerAddr();
} catch (Throwable e) {
log.error("ScheduledTask fetchNameServerAddr exception", e);
}
}
}, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS);
}
//DLedger略过
if (!messageStoreConfig.isEnableDLegerCommitLog()) {
if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) {
if (this.messageStoreConfig.getHaMasterAddress() != null && this.messageStoreConfig.getHaMasterAddress().length() >= 6) {
this.messageStore.updateHaMasterAddress(this.messageStoreConfig.getHaMasterAddress());
this.updateMasterHAServerAddrPeriodically = false;
} else {
this.updateMasterHAServerAddrPeriodically = true;
}
} else {
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.printMasterAndSlaveDiff();
} catch (Throwable e) {
log.error("schedule printMasterAndSlaveDiff error.", e);
}
}
}, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
}
}
//tls略过
if (TlsSystemConfig.tlsMode != TlsMode.DISABLED) {
// Register a listener to reload SslContext
try {
fileWatchService = new FileWatchService(
new String[] {
TlsSystemConfig.tlsServerCertPath,
TlsSystemConfig.tlsServerKeyPath,
TlsSystemConfig.tlsServerTrustCertPath
},
new FileWatchService.Listener() {
boolean certChanged, keyChanged = false;
@Override
public void onChanged(String path) {
if (path.equals(TlsSystemConfig.tlsServerTrustCertPath)) {
log.info("The trust certificate changed, reload the ssl context");
reloadServerSslContext();
}
if (path.equals(TlsSystemConfig.tlsServerCertPath)) {
certChanged = true;
}
if (path.equals(TlsSystemConfig.tlsServerKeyPath)) {
keyChanged = true;
}
if (certChanged && keyChanged) {
log.info("The certificate and private key changed, reload the ssl context");
certChanged = keyChanged = false;
reloadServerSslContext();
}
}
private void reloadServerSslContext() {
((NettyRemotingServer) remotingServer).loadSslContext();
((NettyRemotingServer) fastRemotingServer).loadSslContext();
}
});
} catch (Exception e) {
log.warn("FileWatchService created error, can't load the certificate dynamically");
}
}
//初始化事务管理服务
initialTransaction();
//初始化访问鉴权信息
initialAcl();
//初始化rpc调用钩子
initialRpcHooks();
}
//至此,brokerController算是初始化完成,返回结果
return result;
}
5.2 启动
从BrokerStartup类的main函数入口开始,看看调用过程
public static void main(String[] args) {
// 先调用 createBrokerController 创建,创建过程上一节`5.1`已经讲解了;创建完后,开始启动
start(createBrokerController(args));
}
public static BrokerController start(BrokerController controller) {
try {
// 调用 BrokerController.start 启动
controller.start();
String tip = "The broker[" + controller.getBrokerConfig().getBrokerName() + ", "
+ controller.getBrokerAddr() + "] boot success. serializeType=" + RemotingCommand.getSerializeTypeConfigInThisServer();
if (null != controller.getBrokerConfig().getNamesrvAddr()) {
tip += " and name server is " + controller.getBrokerConfig().getNamesrvAddr();
}
log.info(tip);
System.out.printf("%s%n", tip);
return controller;
} catch (Throwable e) {
e.printStackTrace();
System.exit(-1); // 启动失败,退出程序
}
return null;
}
BrokerController.start
public void start() throws Exception {
//开启消息存储处理服务
if (this.messageStore != null) {
this.messageStore.start();
}
//开启netty服务端提供服务
if (this.remotingServer != null) {
this.remotingServer.start();
}
//开启netty服务端提供快速通道服务
if (this.fastRemotingServer != null) {
this.fastRemotingServer.start();
}
//tsl相关的,不介绍
if (this.fileWatchService != null) {
this.fileWatchService.start();
}
//启动broker作为客户端与namesrv的交互服务
if (this.brokerOuterAPI != null) {
this.brokerOuterAPI.start();
}
//这个服务是给消费端拉取消息时,当前broker的cq中还没有消息,那么broker先hold住这个拉取请求,然后通过pullRequestHoldService线程轮询检查是否有hold住的需求,并在消息来到后,通知客户端连接线程,并将消息发出
if (this.pullRequestHoldService != null) {
this.pullRequestHoldService.start();
}
//启动broker总管服务线程,每10秒扫描一次客户端(发送、消费、查询)连接,将长期(默认2分钟)未激活(其实就是没心跳了)的通道关闭
if (this.clientHousekeepingService != null) {
this.clientHousekeepingService.start();
}
if (this.filterServerManager != null) {
this.filterServerManager.start();
}
if (!messageStoreConfig.isEnableDLegerCommitLog()) {
startProcessorByHa(messageStoreConfig.getBrokerRole());
handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
}
//注册broker信息到namesrv
this.registerBrokerAll(true, false, true);
//定时任务,定期更新注册broker信息到namesrv
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister());
} catch (Throwable e) {
log.error("registerBrokerAll Exception", e);
}
}
}, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod(), 60000)), TimeUnit.MILLISECONDS);
if (this.brokerStatsManager != null) {
this.brokerStatsManager.start();
}
if (this.brokerFastFailure != null) {
this.brokerFastFailure.start();
}
//至此启动结束
}