第五章-Broker-创建和启动

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();
    }
    //至此启动结束

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

多栖码农

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值