rocketmq源码解析broker启动①

说在前面

broker启动

 

源码解析

进入方法,org.apache.rocketmq.broker.BrokerStartup#main

   public static void main(String[] args) {//        创建brokerController并启动=》        start(createBrokerController(args));    }

进入方法,创建brokerController并启动,org.apache.rocketmq.broker.BrokerStartup#createBrokerController

 public static BrokerController createBrokerController(String[] args) {        System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, Integer.toString(MQVersion.CURRENT_VERSION));
//        设置发送的缓冲区大小        if (null == System.getProperty(NettySystemConfig.COM_ROCKETMQ_REMOTING_SOCKET_SNDBUF_SIZE)) {            NettySystemConfig.socketSndbufSize = 131072;        }
//        设置接收到的缓冲区大小        if (null == System.getProperty(NettySystemConfig.COM_ROCKETMQ_REMOTING_SOCKET_RCVBUF_SIZE)) {            NettySystemConfig.socketRcvbufSize = 131072;        }
        try {            //PackageConflictDetect.detectFastjson(); 构建命令行操作=》            Options options = ServerUtil.buildCommandlineOptions(new Options());//            mqbroker 启动broker命令            commandLine = ServerUtil.parseCmdLine("mqbroker", args, buildCommandlineOptions(options),                new PosixParser());            if (null == commandLine) {                System.exit(-1);            }
//            broker配置            final BrokerConfig brokerConfig = new BrokerConfig();//            server配置            final NettyServerConfig nettyServerConfig = new NettyServerConfig();//            client配置            final NettyClientConfig nettyClientConfig = new NettyClientConfig();
            nettyClientConfig.setUseTLS(Boolean.parseBoolean(System.getProperty(TLS_ENABLE,                String.valueOf(TlsSystemConfig.tlsMode == TlsMode.ENFORCING))));//            broker默认端口            nettyServerConfig.setListenPort(10911);//            消息存储配置            final MessageStoreConfig messageStoreConfig = new MessageStoreConfig();
//            如果是从节点命中率降低            if (BrokerRole.SLAVE == messageStoreConfig.getBrokerRole()) {                int ratio = messageStoreConfig.getAccessMessageInMemoryMaxRatio() - 10;                messageStoreConfig.setAccessMessageInMemoryMaxRatio(ratio);            }
//            解析命令行c指定的配置文件属性            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);
//                    默认broker配置文件 System.getProperty("user.home") + File.separator + "store"//                    + File.separator + "config" + File.separator + "broker.properties"//                    设置broker配置文件                    BrokerPathConfigHelper.setBrokerConfigPath(file);                    in.close();                }            }
//            命令行指定的属性解析成properties对象并解析成对象            MixAll.properties2Object(ServerUtil.commandLine2Properties(commandLine), brokerConfig);
            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);            }
//            从系统变量rocketmq.namesrv.addr中获取namesrv的地址            String namesrvAddr = brokerConfig.getNamesrvAddr();            if (null != namesrvAddr) {                try {//                    多个namesrv地址是用;分开的                    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);                }            }
            switch (messageStoreConfig.getBrokerRole()) {                case ASYNC_MASTER:                case SYNC_MASTER:                    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;            }
//            ha broker监听端口 10912            messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);            LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();            JoranConfigurator configurator = new JoranConfigurator();            configurator.setContext(lc);            lc.reset();//            broker logback配置文件            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            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);            }
//            jdk提供的虚拟机关闭的钩子方法            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;    }

进入方法,构建命令行操作,org.apache.rocketmq.srvutil.ServerUtil#buildCommandlineOptions

 public static Options buildCommandlineOptions(final Options options) {        Option opt = new Option("h", "help", false, "Print help");        opt.setRequired(false);        options.addOption(opt);
//        这里可以看到启动的时候有一个n参数指定namesrv的地址,可以是单机可以是集群,启动地址之间用;分开        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;    }

进入方法,初始化控制器,org.apache.rocketmq.broker.BrokerController#initialize

  public boolean initialize() throws CloneNotSupportedException {//        加载topic config/topics.json=》        boolean result = this.topicConfigManager.load();
//        加载客户消费的offset config/consumerOffset.json        result = result && this.consumerOffsetManager.load();//        加载订阅组信息 config/subscriptionGroup.json        result = result && this.subscriptionGroupManager.load();//        加载客户filter config/consumerFilter.json        result = result && this.consumerFilterManager.load();
        if (result) {            try {                this.messageStore =                    new DefaultMessageStore(this.messageStoreConfig, this.brokerStatsManager, this.messageArrivingListener,                        this.brokerConfig);                this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore);                //load plugin                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);            }        }
//        从消息存储中加载=》        result = result && this.messageStore.load();
        if (result) {            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);            this.sendMessageExecutor = new BrokerFixedThreadPoolExecutor(//                    发送消息线程数默认值是1                this.brokerConfig.getSendMessageThreadPoolNums(),                this.brokerConfig.getSendMessageThreadPoolNums(),                1000 * 60,                TimeUnit.MILLISECONDS,                this.sendThreadPoolQueue,                new ThreadFactoryImpl("SendMessageThread_"));
            this.pullMessageExecutor = new BrokerFixedThreadPoolExecutor(//                    拉取消息默认线程数 2倍的可用线程数+16                this.brokerConfig.getPullMessageThreadPoolNums(),                this.brokerConfig.getPullMessageThreadPoolNums(),                1000 * 60,                TimeUnit.MILLISECONDS,                this.pullThreadPoolQueue,                new ThreadFactoryImpl("PullMessageThread_"));
            this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(//                    查询线程数的默认线程数 8+可用线程数                this.brokerConfig.getQueryMessageThreadPoolNums(),                this.brokerConfig.getQueryMessageThreadPoolNums(),                1000 * 60,                TimeUnit.MILLISECONDS,                this.queryThreadPoolQueue,                new ThreadFactoryImpl("QueryMessageThread_"));
//            管理服务核心线程数默认值是16            this.adminBrokerExecutor =                Executors.newFixedThreadPool(this.brokerConfig.getAdminBrokerThreadPoolNums(), new ThreadFactoryImpl(                    "AdminBrokerThread_"));
//            client管理服务默认核心线程数32            this.clientManageExecutor = new ThreadPoolExecutor(                this.brokerConfig.getClientManageThreadPoolNums(),                this.brokerConfig.getClientManageThreadPoolNums(),                1000 * 60,                TimeUnit.MILLISECONDS,                this.clientManagerThreadPoolQueue,                new ThreadFactoryImpl("ClientManageThread_"));
//            broker心跳监测核心线程数默认值是可用线程数或32            this.heartbeatExecutor = new BrokerFixedThreadPoolExecutor(                this.brokerConfig.getHeartbeatThreadPoolNums(),                this.brokerConfig.getHeartbeatThreadPoolNums(),                1000 * 60,                TimeUnit.MILLISECONDS,                this.heartbeatThreadPoolQueue,                new ThreadFactoryImpl("HeartbeatThread_",true));

//            消费者管理服务核心线程数默认值是32            this.consumerManageExecutor =                Executors.newFixedThreadPool(this.brokerConfig.getConsumerManageThreadPoolNums(), new ThreadFactoryImpl(                    "ConsumerManageThread_"));
//            注册处理器=》            this.registerProcessor();
//            初始化延迟时间            final long initialDelay = UtilAll.computNextMorningTimeMillis() - System.currentTimeMillis();            final long period = 1000 * 60 * 60 * 24;            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);
            this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {                @Override                public void run() {                    try {//                        消费者offset持久化=》                        BrokerController.this.consumerOffsetManager.persist();                    } catch (Throwable e) {                        log.error("schedule persist consumerOffset error.", e);                    }                }            }, 1000 * 10, this.brokerConfig.getFlushConsumerOffsetInterval(), TimeUnit.MILLISECONDS);
            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);
            this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {                @Override                public void run() {                    try {//                        broker保护机制 =》                        BrokerController.this.protectBroker();                    } catch (Throwable e) {                        log.error("protectBroker error.", e);                    }                }            }, 3, 3, TimeUnit.MINUTES);
            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);
            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);
            if (this.brokerConfig.getNamesrvAddr() != null) {//                更新namesrv地址                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);            }
            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;                }
                this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                    @Override                    public void run() {                        try {//                            主从同步=》                            BrokerController.this.slaveSynchronize.syncAll();                        } catch (Throwable e) {                            log.error("ScheduledTask syncAll slave exception", e);                        }                    }//                    延迟10s,60s同步一次                }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);            } else {                this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
                    @Override                    public void run() {                        try {//                            打印master和slave当前的offset                            BrokerController.this.printMasterAndSlaveDiff();                        } catch (Throwable e) {                            log.error("schedule printMasterAndSlaveDiff error.", e);                        }                    }                }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);            }
            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();        }        return result;    }

进入方法,加载topic config/topics.json,org.apache.rocketmq.common.ConfigManager#load

 public boolean load() {        String fileName = null;        try {//            System.getProperty("user.home") + File.separator + "store" File.separator + "config" + File.separator + "topics.json" 获取topic配置文件            fileName = this.configFilePath();            String jsonString = MixAll.file2String(fileName);
            if (null == jsonString || jsonString.length() == 0) {//                文件备份=》                return this.loadBak();            } else {//                配置反序列化=》                this.decode(jsonString);                log.info("load " + fileName + " OK");                return true;            }        } catch (Exception e) {            log.error("load " + fileName + " failed, and try to load backup file", e);            return this.loadBak();        }    }

进入方法,文件备份,org.apache.rocketmq.common.ConfigManager#loadBak

 private boolean loadBak() {        String fileName = null;        try {            fileName = this.configFilePath();//            从备份配置文件中读取配置            String jsonString = MixAll.file2String(fileName + ".bak");            if (jsonString != null && jsonString.length() > 0) {//                配置反序列化=》                this.decode(jsonString);                log.info("load " + fileName + " OK");                return true;            }        } catch (Exception e) {            log.error("load " + fileName + " Failed", e);            return false;        }
        return true;    }

进入方法,从消息存储中加载,org.apache.rocketmq.store.DefaultMessageStore#load

  public boolean load() {        boolean result = true;
        try {            boolean lastExitOK = !this.isTempFileExist();            log.info("last shutdown {}", lastExitOK ? "normally" : "abnormally");
            if (null != scheduleMessageService) {//                消息加载=》                result = result && this.scheduleMessageService.load();            }
            // load Commit Log 加载commitLog=》            result = result && this.commitLog.load();
            // load Consume Queue 记载消费队列=》            result = result && this.loadConsumeQueue();//          System.getProperty("user.home") + File.separator + "store" File.separator + "checkpoint" 创建存储检查对象            if (result) {                this.storeCheckpoint =                    new StoreCheckpoint(StorePathConfigHelper.getStoreCheckpoint(this.messageStoreConfig.getStorePathRootDir()));
                this.indexService.load(lastExitOK);
//                恢复=》                this.recover(lastExitOK);
                log.info("load over, and the max phy offset = {}", this.getMaxPhyOffset());            }        } catch (Exception e) {            log.error("load exception", e);            result = false;        }
        if (!result) {            this.allocateMappedFileService.shutdown();        }
        return result;    }

进入方法,消息加载,org.apache.rocketmq.store.schedule.ScheduleMessageService#load

  public boolean load() {//        =》        boolean result = super.load();//        解析延迟等级=》        result = result && this.parseDelayLevel();        return result;    }

进入方法,解析延迟等级,org.apache.rocketmq.store.schedule.ScheduleMessageService#parseDelayLevel

public boolean parseDelayLevel() {        HashMap<String, Long> timeUnitTable = new HashMap<String, Long>();        timeUnitTable.put("s", 1000L);        timeUnitTable.put("m", 1000L * 60);        timeUnitTable.put("h", 1000L * 60 * 60);        timeUnitTable.put("d", 1000L * 60 * 60 * 24);
        String levelString = this.defaultMessageStore.getMessageStoreConfig().getMessageDelayLevel();        try {            String[] levelArray = levelString.split(" ");            for (int i = 0; i < levelArray.length; i++) {                String value = levelArray[i];                String ch = value.substring(value.length() - 1);                Long tu = timeUnitTable.get(ch);
                int level = i + 1;                if (level > this.maxDelayLevel) {                    this.maxDelayLevel = level;                }                long num = Long.parseLong(value.substring(0, value.length() - 1));                long delayTimeMillis = tu * num;                this.delayLevelTable.put(level, delayTimeMillis);            }        } catch (Exception e) {            log.error("parseDelayLevel exception", e);            log.info("levelString String = {}", levelString);            return false;        }
        return true;    }

返回方法,加载commitLog,org.apache.rocketmq.store.CommitLog#load

  public boolean load() {//        映射文件队列加载=》        boolean result = this.mappedFileQueue.load();        log.info("load commit log " + (result ? "OK" : "Failed"));        return result;    }

进入方法,映射文件队列加载,org.apache.rocketmq.store.MappedFileQueue#load

 public boolean load() {//        System.getProperty("user.home") + File.separator + "store"//            + File.separator + "commitlog"        File dir = new File(this.storePath);        File[] files = dir.listFiles();        if (files != null) {            // ascending order            Arrays.sort(files);            for (File file : files) {
//                队列映射文件的大小不等于1G                if (file.length() != this.mappedFileSize) {                    log.warn(file + "\t" + file.length()                        + " length not matched message store config value, ignore it");                    return true;                }
                try {//                    创建映射文件=》                    MappedFile mappedFile = new MappedFile(file.getPath(), mappedFileSize);
                    mappedFile.setWrotePosition(this.mappedFileSize);                    mappedFile.setFlushedPosition(this.mappedFileSize);                    mappedFile.setCommittedPosition(this.mappedFileSize);                    this.mappedFiles.add(mappedFile);                    log.info("load " + file.getPath() + " OK");                } catch (IOException e) {                    log.error("load file " + file + " error", e);                    return false;                }            }        }
        return true;    }

接下篇。

 

说在最后

本次解析仅代表个人观点,仅供参考。

 

加入技术微信群

钉钉技术群

转载于:https://my.oschina.net/u/3775437/blog/3097027

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值