【RocketMQ | 源码分析】Broker启动过程(超详细)

688 阅读7分钟

前言

Broker的作用主要负责消息的存储、投递和查询以及服务高可用保证。Broker是RocketMQ中最重要也是最复杂的组件,本篇文章是Broker源码分析的第一篇,通过本篇文章,可以对Broker有一个初步、整体的认识。文章中的代码几乎逐行加了注释,尽可能让把相关的类都介绍了一遍,方便后续深入学习Broker其他知识。

Broker简介

简介内容截取自官网

Broker架构介绍

在 Master-Slave 架构中,Broker 分为 Master 与 Slave。一个Master可以对应多个Slave,但是一个Slave只能对应一个Master。Master 与 Slave 的对应关系通过指定相同的BrokerName,不同的BrokerId 来定义,BrokerId为0表示Master,非0表示Slave。Master也可以部署多个。

Broker部署模型

  • 每个 BrokerNameServer 集群中的所有节点建立长连接,定时注册 Topic 信息到所有 NameServer。
  • ProducerNameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取Topic路由信息,并向提供 Topic 服务的 Master 建立长连接,且定时向 Master 发送心跳。Producer 完全无状态。
  • ConsumerNameServer 集群中的其中一个节点建立长连接,定期从 NameServer 获取 Topic 路由信息,并向提供 Topic 服务的 Master、Slave 建立长连接,且定时向 Master、Slave发送心跳。Consumer 既可以从 Master 订阅消息,也可以从Slave订阅消息。

Broker启动过程源码分析

Broker启动的入口方法在org.apache.rocketmq.broker.BrokerStartup#main,如下所示,它与namesrv的启动过程有一些相似,主要是下面两个步骤

  • 读取配置,并创建BrokerController

  • 启动BrokerController

public static void main(String[] args) {
    // 读取配置文件,创建BrokerController并启动
    start(createBrokerController(args));
}
创建BrokerController过程

创建BrokerController的方法在BrokerStartup#createBrokerController,这个方法创建BrokerController的核心逻辑如下

  1. 创建配置类BrokerConfig、NettyServerConfig、NettyClientConfig和MessageStoreConfig
  2. 解析命令行中-c对应的broker.conf配置,并将配置设置到上面的配置类中
  3. 校验环境变量中的ROCKETMQ_HOME是否存在,校验namesrvAddr是否正确
  4. 设置haListenPort端口(remotingServer监听端口(10911)+1),它用于Broker主从同步
  5. 通过上面4个配置创建BrokerController
  6. 调用BrokerController#initialize初始化
  7. 注册进程关闭的钩子函数
    public static BrokerController createBrokerController(String[] args) {
        try {
            // 如果启动命令不是mqbroker,则直接退出
            Options options = ServerUtil.buildCommandlineOptions(new Options());
            commandLine = ServerUtil.parseCmdLine("mqbroker", args, buildCommandlineOptions(options),
                new PosixParser());
            if (null == commandLine) {
                System.exit(-1);
            }
            // 创建broker的配置类,例如brokerClusterName,brokerName默认是本机hostname、brokerId
            final BrokerConfig brokerConfig = new BrokerConfig();
            // NettyServer配置类,broker作为服务端的配置类
            final NettyServerConfig nettyServerConfig = new NettyServerConfig();
            // NettyClient配置类,broker作为客户端的配置类
            final NettyClientConfig nettyClientConfig = new NettyClientConfig();
            // tls相关配置类
            nettyClientConfig.setUseTLS(Boolean.parseBoolean(System.getProperty(TLS_ENABLE,
                String.valueOf(TlsSystemConfig.tlsMode == TlsMode.ENFORCING))));
            // nettyServerConfig监听端口
            nettyServerConfig.setListenPort(10911);
            // 消息存储配置
            final MessageStoreConfig messageStoreConfig = new MessageStoreConfig();
            // 如果是Master节点,则消息占用内存百分比为40(默认)
            // 如果是Slave节点,则消息占用内存百分比为30
            if (BrokerRole.SLAVE == messageStoreConfig.getBrokerRole()) {
                int ratio = messageStoreConfig.getAccessMessageInMemoryMaxRatio() - 10;
                messageStoreConfig.setAccessMessageInMemoryMaxRatio(ratio);
            }
            // 读取命令行'-c' 参数中的配置文件,并且设置到brokerConfig,nettyServerConfig,nettyClientConfig,messageStoreConfig
            if (commandLine.hasOption('c')) {
                String file = commandLine.getOptionValue('c');
                if (file != null) {
                    configFile = file;
                    InputStream in = new BufferedInputStream(new FileInputStream(file));
                    properties = new Properties();
                    // ... 读取配置
                }
            }
						// 校验环境变量中是否设置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);
            }
            // 校验nameserAddr地址
            String namesrvAddr = brokerConfig.getNamesrvAddr();
            if (null != namesrvAddr) {
                try {
                    String[] addrArray = namesrvAddr.split(";");
                    for (String addr : addrArray) {
                        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);
                }
            }
            // 根据BrokerRole设置BrokerId,默认是ASYNC_MASTER
            // 如果是ASYNC_MASTER,则不处理
            // 如果是SYNC_MASTER,将MASTER_ID设置为0
            // 如果是SLAVE,
            switch (messageStoreConfig.getBrokerRole()) {
                case ASYNC_MASTER:
                case SYNC_MASTER:
                    brokerConfig.setBrokerId(MixAll.MASTER_ID);
                    break;
                case SLAVE:
                    if (brokerConfig.getBrokerId() <= 0) {
                        System.out.printf("Slave's brokerId must be > 0");
                        System.exit(-3);
                    }

                    break;
                default:
                    break;
            }
						// ...
            // 消息存储监听端口 nettyServerPort+1
            messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);
						// ...
            configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/logback_broker.xml");
            // 启动命令中包含'-p'参数,打印所有配置参数,并退出
            if (commandLine.hasOption('p')) {
                InternalLogger console = InternalLoggerFactory.getLogger(LoggerName.BROKER_CONSOLE_NAME);
                MixAll.printObjectProperties(console, brokerConfig);
              	// ...
                System.exit(0);
                // 启动命令中包含'-m'参数,打印重要参数,并退出
            } else if (commandLine.hasOption('m')) {
                InternalLogger console = InternalLoggerFactory.getLogger(LoggerName.BROKER_CONSOLE_NAME);
                MixAll.printObjectProperties(console, brokerConfig, true);
                // ...
                System.exit(0);
            }
						// ...
						// 创建broker
            final BrokerController controller = new BrokerController(
                brokerConfig,
                nettyServerConfig,
                nettyClientConfig,
                messageStoreConfig);
            // 配置记录在Controller中的Configuration中
            controller.getConfiguration().registerConfig(properties);
            // controller初始化
            boolean initResult = controller.initialize();
          	// 初始化失败,则退出 
            if (!initResult) {
                controller.shutdown();
                System.exit(-3);
            }
            // 添加shutdownHook
            Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
   							//... 增加日志打印
            }, "ShutdownHook"));
            return controller;
        } catch (Throwable e) {
            e.printStackTrace();
            System.exit(-1);
        }

        return null;
    }
BrokerController构造过程

从下面源码可以看出,BrokerController在创建的过程也会创建很多配置类,线程池队列,各种Manager,Service,Listener等,BrokerController是Broker的大管家,也是Broker的中央控制器。在这里创建的每个处理器,管理器,监听器类都是相当重要的。

通过这个构造方法,可以看出BrokerController在Broker的地位是相当,相当,相当重要的!!!

BrokerController对于Broker来说有点像ApplicationContext在Spring Framework中的地位,DispatcherServlet在Spring MVC中的地位

    public BrokerController(
        final BrokerConfig brokerConfig,
        final NettyServerConfig nettyServerConfig,
        final NettyClientConfig nettyClientConfig,
        final MessageStoreConfig messageStoreConfig
    ) {
        // 设置配置
        this.brokerConfig = brokerConfig;
        this.nettyServerConfig = nettyServerConfig;
        this.nettyClientConfig = nettyClientConfig;
        this.messageStoreConfig = messageStoreConfig;
        //消费者偏移量Manager,主要用于维护offset进度信息,默认是false,会创建ConsumerOffsetManager
        this.consumerOffsetManager = messageStoreConfig.isEnableLmq() ? new LmqConsumerOffsetManager(this) : new ConsumerOffsetManager(this);
        // topic配置Manager,默认是false,会创建TopicConfigManager
        this.topicConfigManager = messageStoreConfig.isEnableLmq() ? new LmqTopicConfigManager(this) : new TopicConfigManager(this);
        // 拉消息处理器,用于处理要拉去的消息
        this.pullMessageProcessor = new PullMessageProcessor(this);
        // 拉取消息挂起服务,如果没有要拉的消息,通过长轮询机制挂起Consumer的请求
        this.pullRequestHoldService = messageStoreConfig.isEnableLmq() ? new LmqPullRequestHoldService(this) : new PullRequestHoldService(this);
        // 消息到达Listener,消息到达会通知pullRequestHoldService
        this.messageArrivingListener = new NotifyMessageArrivingListener(this.pullRequestHoldService);
        // 消费者id变化Listener
        this.consumerIdsChangeListener = new DefaultConsumerIdsChangeListener(this);
        // 消费者Manager,用于维护消费者组的注册实例信息以及topic订阅信息,并且会监听consumerId的变化
        this.consumerManager = new ConsumerManager(this.consumerIdsChangeListener);
        // 消费者过滤器,配置在本地
        this.consumerFilterManager = new ConsumerFilterManager(this);
        // 生产者Manager
        this.producerManager = new ProducerManager();
        // 客户端心跳保持服务,用于定时扫描生产者和消费者客户端,并且将移除不活跃的客户端通道及相关信息
        this.clientHousekeepingService = new ClientHousekeepingService(this);
        // 处理某些broker到客户端请求,例如重置offset等
        this.broker2Client = new Broker2Client(this);
        // 订阅分组关系Manager,默认是false,创建SubscriptionGroupManager
        this.subscriptionGroupManager = messageStoreConfig.isEnableLmq() ? new LmqSubscriptionGroupManager(this) : new SubscriptionGroupManager(this);
        // broker对外发请求API,例如注销broker,注册broker,向master,slave发起请求
        this.brokerOuterAPI = new BrokerOuterAPI(nettyClientConfig);
        // 过滤服务管理器
        this.filterServerManager = new FilterServerManager(this);
        // 从节点同步器,定时向主节点发起同步请求,例如topic配置,消费位移
        this.slaveSynchronize = new SlaveSynchronize(this);
        // 处理来自生产者发送消息请求队列,默认10000
        this.sendThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getSendThreadPoolQueueCapacity());
        // 生产者推送消息处理完成之后回调线程池队列,默认10000
        this.putThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getPutThreadPoolQueueCapacity());
        // 消费者拉取消息请求队列,默认100000
        this.pullThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getPullThreadPoolQueueCapacity());
        // 处理reply消息的请求的队列,RocketMQ4.7.0版本中增加了request-reply新特性,该特性允许producer在发送消息后同步或者异步等待consumer消费完消息并返回响应消息,类似rpc调用效果。
        // 即生产者发送了消息之后,可以同步或者异步的收到消费了这条消息的消费者的响应,默认10000
        this.replyThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getReplyThreadPoolQueueCapacity());
        // 处理查询请求队列,默认20000
        this.queryThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getQueryThreadPoolQueueCapacity());
        // 客户端管理器队列,默认1000000,用于处理客户端注销请求等
        this.clientManagerThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getClientManagerThreadPoolQueueCapacity());
        // 消费者管理器队列,默认1000000,目前好像没用到o(╥﹏╥)o
        this.consumerManagerThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getConsumerManagerThreadPoolQueueCapacity());
        // 心跳处理队列,默认50000,用于处理客户端的心跳
        this.heartbeatThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getHeartbeatThreadPoolQueueCapacity());
        // 事务消息相关处理的队列,默认100000
        this.endTransactionThreadPoolQueue = new LinkedBlockingQueue<>(this.brokerConfig.getEndTransactionPoolQueueCapacity());
        // broker状态管理器,用于保存broker的状态
        this.brokerStatsManager = messageStoreConfig.isEnableLmq() ? new LmqBrokerStatsManager(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.isEnableDetailStat()) : new BrokerStatsManager(this.brokerConfig.getBrokerClusterName(), this.brokerConfig.isEnableDetailStat());
        // 存储的ip信息,目前好像没用到
        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初始化过程

BrokerController创建完成之后,就进行BrokerController初始化,初始化完成之后,BrokerController就算创建完成了,初始化过程可以总结为如下步骤

  1. 加载本地配置文件
    • Topic配置文件(TopicConfigManager)
    • 消费者消费偏移量配置文件(ConsumerOffsetManager)
    • 订阅分组配置文件(SubscriptionGroupManager)
    • 消费者过滤配置文件(ConsumerFilterManager)
  2. 加载消息存储类(DefaultMessageStore)
  3. 创建Broker服务端通信类NettyRemotingServer
  4. 注册处理器到NettyRemotingServer
  5. 创建了很多定时任务线程池
    • 每隔24小时打印前一天生产和消费数量
    • 每隔5s将消费者offset持久化
    • 每隔10s将消费过滤信息持久化
    • 每隔3min,检查消费者消费进度
    • 每隔1s打印发送线程池队列信息
    • 如果开启fetchNamesrvAddrByAddressServer
      • 每隔2min 从配置地址,获取namesrvAddr
  6. 如果没有开启DLeger,并且当前节点是broker节点,则每隔1min打印主从节点差异
  7. 创建文件监听器
  8. 初始化事务相关服务
  9. 初始化权限相关服务
  10. 初始化RPC调用钩子函数
public boolean initialize() throws CloneNotSupportedException {
        // Topic配置文件加载,加载路径:${user.home}/store/config/topics.json
        boolean result = this.topicConfigManager.load();
        // 消费者消费偏移量配置文件加载,加载路径:${user.home}/store/config/consumerOffset.json
        result = result && this.consumerOffsetManager.load();
        // 订阅分组配置文件加载,加载路径:${user.home}/store/config/subscriptionGroup.json
        result = result && this.subscriptionGroupManager.load();
        // 消费者过滤配置文件加载,加载路径:${user.home}/store/config/consumerFilter.json
        result = result && this.consumerFilterManager.load();

        if (result) {
            try {
                // 消息存储类
                this.messageStore =
                    new DefaultMessageStore(this.messageStoreConfig, this.brokerStatsManager, this.messageArrivingListener,
                        this.brokerConfig);
                // enableDLegerCommitLog配置是是否允许自动主从切换,默认是false,主从配置是从4.5版本之后的新功能
                // 如果开启了允许主从切换,则会创建DLedgerRoleChangeHandler处理器类
                if (messageStoreConfig.isEnableDLegerCommitLog()) {
                    DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore);
                    ((DLedgerCommitLog)((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
                }
                this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore);
                // 加载消息存储插件
                MessageStorePluginContext context = new MessageStorePluginContext(messageStoreConfig, brokerStatsManager, messageArrivingListener, brokerConfig);
                this.messageStore = MessageStoreFactory.build(context, this.messageStore);
                // 添加消息过滤器
                this.messageStore.getDispatcherList().addFirst(new CommitLogDispatcherCalcBitMap(this.brokerConfig, this.consumerFilterManager));
            } catch (IOException e) {
                result = false;
                log.error("Failed to initialize", e);
            }
        }
        // 消息存储类加载,默认是DefaultMessageStore
        result = result && this.messageStore.load();

        if (result) {
            // 远程通信服务类
            this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.clientHousekeepingService);
            // 远程服务配置监听端口类 默认端口是服务监听端口-2,10909
            NettyServerConfig fastConfig = (NettyServerConfig) this.nettyServerConfig.clone();
            fastConfig.setListenPort(nettyServerConfig.getListenPort() - 2);
            this.fastRemotingServer = new NettyRemotingServer(fastConfig, this.clientHousekeepingService);
            // 处理发送消息请求线程池,默认线程数量:min(处理器数量,4)
            this.sendMessageExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // 生产者推送消息处理完成线程池,默认线程数量:min(处理器数量,4)
            this.putMessageFutureExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // 消费者拉取消息线程池,默认线程数量:16+处理器数量*2
            this.pullMessageExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // 消费者消费消息响应线程池,默认线程数量:16+处理器数量*2
            this.replyMessageExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // 查询消息线程池:默认线程池数量:8+处理器数量
            this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // broker管理线程池,默认线程数量:16
            this.adminBrokerExecutor =
                Executors.newFixedThreadPool(/*...*/);
            // 客户端管理线程池
            this.clientManageExecutor = new ThreadPoolExecutor(/*...*/);
            // 心跳处理线程池
            this.heartbeatExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // 事务处理线程池
            this.endTransactionExecutor = new BrokerFixedThreadPoolExecutor(/*...*/);
            // 消费者管理线程池
            this.consumerManageExecutor =
                Executors.newFixedThreadPool(/*...*/);
            // 请求处理器注册,注册到RemotingServer
            this.registerProcessor();

            final long initialDelay = UtilAll.computeNextMorningTimeMillis() - System.currentTimeMillis();
            final long period = 1000 * 60 * 60 * 24;
            // 每隔24小时打印前一天生产和消费数量
            this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            // 每隔5s将消费者offset持久化
            this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            // 每隔10s将消费过滤信息持久化
            this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            // 每隔3min,检查消费者消费进度,开启disableConsumeIfConsumerReadSlowly时生效,默认是false
            // 当消费进度落后阈值时,就会停止消费者组,保护broker
            this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            // 每隔1s打印发送消息线程池队列、拉取消息线程池队列、查询消息线程池队列、结束事务线程池队列的大小,队列头部元素存活时间
            this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            // 每隔1min打印在commitLog中提交,但是还没分配到consumerQueue的字节数
            this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            if (this.brokerConfig.getNamesrvAddr() != null) {
                // 如果brokerConfig中namesrvAddr不为空,则每隔2min更新remotingClient中的namesrvAddr
                this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr());
                this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
            // 如果打开fetchNamesrvAddrByAddressServer配置
            // 每隔2min 从配置地址,获取namesrvAddr
            // 地址如下:http://${rocketmq.namesrv.domain}/rocketmq/${rocketmq.namesrv.domain.subgroup}
            } else if (this.brokerConfig.isFetchNamesrvAddrByAddressServer()) {
                this.scheduledExecutorService.scheduleAtFixedRate(() -> {
                    try {
                        BrokerController.this.brokerOuterAPI.fetchNameServerAddr();
                    } catch (Throwable e) {
                        log.error("ScheduledTask fetchNameServerAddr exception", e);
                    }
                }, 1000 * 10, 1000 * 60 * 2, TimeUnit.MILLISECONDS);
            }
            // 如果没有开启高可用服务,配置enableDLegerCommitLog,默认就是没有开启
            if (!messageStoreConfig.isEnableDLegerCommitLog()) {
                // 如果当前broker是从节点
                if (BrokerRole.SLAVE == this.messageStoreConfig.getBrokerRole()) {
                    // 根据是否配置了HA地址,来更新HA地址
                    if (this.messageStoreConfig.getHaMasterAddress() != null && this.messageStoreConfig.getHaMasterAddress().length() >= 6) {
                        this.messageStore.updateHaMasterAddress(this.messageStoreConfig.getHaMasterAddress());
                        this.updateMasterHAServerAddrPeriodically = false;
                    } else {
                        this.updateMasterHAServerAddrPeriodically = true;
                    }
                // 如果当前节点是主节点
                } else {
                    // 每隔60s打印主从节点差异
                    this.scheduledExecutorService.scheduleAtFixedRate(/*...*/);
                }
            }
            // TSL文件传输配置,是通信安全的文件监听模块
            // 默认配置是PERMISSIVE,因此会进入代码块
            if (TlsSystemConfig.tlsMode != TlsMode.DISABLED) {
							// ... 省略文件监听代码
            }
            // 初始化事务相关服务
            initialTransaction();
            // 初始化权限相关服务
            initialAcl();
            // 初始化RPC调用钩子函数
            initialRpcHooks();
        }
        return result;
    }
BrokerController启动过程

BrokerController启动过程调用了BrokerController#start,代码如下删除了部分不影响源码分析的代码,整个启动过程主要包括下面两个方面

  • 启动本地服务类
  • 给namesrv发送心跳
public void start() throws Exception {
        // 消息存储类实现类
            this.messageStore.start(); 
        // netty网络服务端启动
            this.remotingServer.start();   
        // netty网络服务端启动
            this.fastRemotingServer.start();  
        // 文件MD5校验
            this.fileWatchService.start(); 
        // 网络通信客户端启动
            this.brokerOuterAPI.start(); 
        // 长轮询处理服务
            this.pullRequestHoldService.start();  
        // 客户端活跃连接扫描服务
            this.clientHousekeepingService.start(); 
        // 创建FilterServer
            this.filterServerManager.start();  
        // 默认是关闭,会走里面的逻辑
        if (!messageStoreConfig.isEnableDLegerCommitLog()) {
            // 如果是主节点,则开启事务消息校验/60s
            startProcessorByHa(messageStoreConfig.getBrokerRole());
            // 如果是从节点,则开启数据同步/10s
            handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
            // 给namesrv发送心跳
            this.registerBrokerAll(true, false, true);
        }
        // 每隔30s发送一次心跳给namesrv
        this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
						// ...
            BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister());
 						// ...
        }, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod()/*30s*/, 60000)), TimeUnit.MILLISECONDS);
        // broker状态管理
            this.brokerStatsManager.start(); // doing nothing
        // 快速失败服务启动
            this.brokerFastFailure.start();   // BrokerStatsManager
}

总结

Broker启动都是围绕BrokerController展开的,BrokerController扮演着举足轻重的地位,Broker整个启动过程可以分为下面三个阶段,通过学习Broker启动过程源码,对于Broker一些关键组件更加熟悉。

image-20230405164218946