rocketmq broker 第三章註冊過程1

   hi 大家好 上兩章介紹了namesrv的啓動和註冊過程,有什麼不對的地方歡迎大家吐槽,接着開始分析broker吧

wKioL1UvaO-y9NPAAAHjYRrPpLA464.jpg

有些地方畫不下了 通過分析看細節吧..

1,createBrokerController

   System.setProperty(RemotingCommand.RemotingVersionKey, Integer.toString(MQVersion.CurrentVersion));

   // Socket發送緩衝區大小
   if (null == System.getProperty(NettySystemConfig.SystemPropertySocketSndbufSize)) {
         NettySystemConfig.SocketSndbufSize = 131072;
   }
   默認發送緩衝區大小128M
   // Socket接收緩衝區大小
   if (null == System.getProperty(NettySystemConfig.SystemPropertySocketRcvbufSize)) {
        NettySystemConfig.SocketRcvbufSize = 131072;
   }

   默認接收緩衝區大小128M

  

   // 檢測包衝突
   PackageConflictDetect.detectFastjson();

   // 解析命令行
   Options options = ServerUtil.buildCommandlineOptions(new Options());
            commandLine = ServerUtil.parseCmdLine("mqbroker", args,                        buildCommandlineOptions(options),
                        new PosixParser());
            if (null == commandLine) {
                System.exit(-1);
                return null;
            }

   2,final BrokerConfig brokerConfig = new BrokerConfig();

    private String rocketmqHome = System.getProperty(MixAll.ROCKETMQ_HOME_PROPERTY,
        System.getenv(MixAll.ROCKETMQ_HOME_ENV));

    獲取rocketMq目錄
    @ImportantField
    private String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY,
        System.getenv(MixAll.NAMESRV_ADDR_ENV));

    獲取namesrc地址
    @ImportantField
    private String brokerIP1 = RemotingUtil.getLocalAddress();

    獲取本地地址
    private String brokerIP2 = RemotingUtil.getLocalAddress();

    獲取本地地址

    @ImportantField
    private String brokerName = localHostName();

    獲取broker hostname
    @ImportantField
    private String brokerClusterName = "DefaultCluster";

    默認集羣名稱
    @ImportantField
    private long brokerId = MixAll.MASTER_ID;

    master集羣ID 必須爲0
    private int brokerPermission = PermName.PERM_READ | PermName.PERM_WRITE;

    broker權限 默認讀與寫
    private int defaultTopicQueueNums = 8;

    默認隊列數量


    // 自動創建Topic功能是否開啓(線上建議關閉)
    @ImportantField
    private boolean autoCreateTopicEnable = true;
    // 自動創建以集羣名字命名的Topic功能是否開啓
    private boolean clusterTopicEnable = true;
    // 自動創建以服務器名字命名的Topic功能是否開啓
    private boolean brokerTopicEnable = true;
    // 自動創建訂閱組功能是否開啓(線上建議關閉)
    @ImportantField
    private boolean autoCreateSubscriptionGroup = true;

    private int sendMessageThreadPoolNums = 16 + Runtime.getRuntime().availableProcessors() * 4;

    發送消息線程池數量
    private int pullMessageThreadPoolNums = 16 + Runtime.getRuntime().availableProcessors() * 2;

    訂閱消息線程池數量
    private int adminBrokerThreadPoolNums = 16;

    adminBroker 線程池數量 各自獨立的線程池 做到線程池隔離

    private int clientManageThreadPoolNums = 16;
    clientManage線程池數量

    private int flushConsumerOffsetInterval = 1000 * 5;
    flush消費端 文件偏移時間戳 默認5秒
    private int flushConsumerOffsetHistoryInterval = 1000 * 60;
    flush消費端 歷史文件偏移時間戳 默認1


    // 是否拒絕接收事務消息
    @ImportantField
    private boolean rejectTransactionMessage = false;

    // 是否從地址服務器尋找Name Server地址,正式發佈後,默認值爲false
    @ImportantField
    private boolean fetchNamesrvAddrByAddressServer = false;

    // 發送消息對應的線程池阻塞隊列size
    private int sendThreadPoolQueueCapacity = 100000;

    // 訂閱消息對應的線程池阻塞隊列size
    private int pullThreadPoolQueueCapacity = 100000;

    // 過濾服務器數量
    private int filterServerNums = 0;

    // Consumer訂閱消息時,Broker是否開啓長輪詢
    private boolean longPollingEnable = true;

    // 如果是短輪詢,服務器掛起時間
    private long shortPollingTimeMills = 1000;

    // notify consumerId changed 開關
    private boolean notifyConsumerIdsChangedEnable = true;

    // slave 是否需要糾正位點
    private boolean offsetCheckInSlave = false;  

   3,final NettyServerConfig nettyServerConfig = new NettyServerConfig();

    netty 服務配置

    private int listenPort = 8888; 監聽端口
    private int serverWorkerThreads = 8;Netty服務工作線程數量

    private int serverCallbackExecutorThreads = 0;Netty服務異步回調線程池線程數量     

    private int serverSelectorThreads = 3;Netty Selector線程數量

    private int serverOnewaySemaphoreValue = 256;控制單向的信號量 一次請求沒有響應

    private int serverAsyncSemaphoreValue = 64;控制異步信號量

    private int serverChannelMaxIdleTimeSeconds = 120;服務空閒心跳檢測時間間隔 單位秒
    private int serverSocketSndBufSize = NettySystemConfig.SocketSndbufSize;

    Netty發送緩衝區大小

    private int serverSocketRcvBufSize = NettySystemConfig.SocketRcvbufSize;

    Netty接受緩衝區大小

    private boolean serverPooledByteBufAllocatorEnable = false;是否使用Netty內存池

   4,final NettyClientConfig nettyClientConfig = new NettyClientConfig();

    private int clientWorkerThreads = 4;Netty客戶端工作線程
    private int clientCallbackExecutorThreads = Runtime.getRuntime().availableProcessors();

    Netty服務異步回調線程池線程數量

    private int clientOnewaySemaphoreValue = NettySystemConfig.ClientOnewaySemaphoreValue;

    控制單向的信號量 一次請求沒有響應

    private int clientAsyncSemaphoreValue = NettySystemConfig.ClientAsyncSemaphoreValue;

    控制異步信號量

    private long connectTimeoutMillis = 3000;

    連接超時時間
    private long channelNotActiveInterval = 1000 * 60;
    掃描channel未激活時間戳
    private int clientChannelMaxIdleTimeSeconds = 120;
    客戶端閒心跳檢測時間間隔 單位秒

    private int clientSocketSndBufSize = NettySystemConfig.SocketSndbufSize;

    客戶端發送緩衝區大小

    private int clientSocketRcvBufSize = NettySystemConfig.SocketRcvbufSize;

    客戶端接受緩衝區大小
    private boolean clientPooledByteBufAllocatorEnable = false;   

    客戶端是否支持netty內存池

    nettyServerConfig.setListenPort(10911);

    監聽端口

   5,final MessageStoreConfig messageStoreConfig = new MessageStoreConfig();

    // 存儲跟目錄
    @ImportantField
    private String storePathRootDir = System.getProperty("user.home") + File.separator + "store";

    // CommitLog存儲目錄
    @ImportantField
    private String storePathCommitLog = System.getProperty("user.home") + File.separator + "store"
            + File.separator + "commitlog";

    // CommitLog每個文件大小 1G
    private int mapedFileSizeCommitLog = 1024 * 1024 * 1024;
    // ConsumeQueue每個文件大小 默認存儲30W條消息
    private int mapedFileSizeConsumeQueue = 300000 * ConsumeQueue.CQStoreUnitSize;
    // CommitLog刷盤間隔時間(單位毫秒)
    @ImportantField
    private int flushIntervalCommitLog = 1000;
    // 是否定時方式刷盤,默認是實時刷盤
    @ImportantField
    private boolean flushCommitLogTimed = false;
    // ConsumeQueue刷盤間隔時間(單位毫秒)
    private int flushIntervalConsumeQueue = 1000;
    // 清理資源間隔時間(單位毫秒)
    private int cleanResourceInterval = 10000;
    // 刪除多個CommitLog文件的間隔時間(單位毫秒)
    private int deleteCommitLogFilesInterval = 100;
    // 刪除多個ConsumeQueue文件的間隔時間(單位毫秒)
    private int deleteConsumeQueueFilesInterval = 100;
    // 強制刪除文件間隔時間(單位毫秒)
    private int destroyMapedFileIntervalForcibly = 1000 * 120;
    // 定期檢查Hanged文件間隔時間(單位毫秒)
    private int redeleteHangedFileInterval = 1000 * 120;
    // 何時觸發刪除文件, 默認凌晨4點刪除文件
    @ImportantField
    private String deleteWhen = "04";
    // 磁盤空間最大使用率
    private int diskMaxUsedSpaceRatio = 75;
    // 文件保留時間(單位小時)
    @ImportantField
    private int fileReservedTime = 72;
    // 寫消息索引到ConsumeQueue,緩衝區高水位,超過則開始流控
    private int putMsgIndexHightWater = 600000;
    // 最大消息大小,默認512K
    private int maxMessageSize = 1024 * 512;
    // 重啓時,是否校驗CRC
    private boolean checkCRCOnRecover = true;
    // 刷CommitLog,至少刷幾個PAGE
    private int flushCommitLogLeastPages = 4;
    // 刷ConsumeQueue,至少刷幾個PAGE
    private int flushConsumeQueueLeastPages = 2;
    // 刷CommitLog,徹底刷盤間隔時間
    private int flushCommitLogThoroughInterval = 1000 * 10;
    // 刷ConsumeQueue,徹底刷盤間隔時間
    private int flushConsumeQueueThoroughInterval = 1000 * 60;
    // 最大被拉取的消息字節數,消息在內存
    @ImportantField
    private int maxTransferBytesOnMessageInMemory = 1024 * 256;
    // 最大被拉取的消息個數,消息在內存
    @ImportantField
    private int maxTransferCountOnMessageInMemory = 32;
    // 最大被拉取的消息字節數,消息在磁盤
    @ImportantField
    private int maxTransferBytesOnMessageInDisk = 1024 * 64;
    // 最大被拉取的消息個數,消息在磁盤
    @ImportantField
    private int maxTransferCountOnMessageInDisk = 8;
    // 命中消息在內存的最大比例
    @ImportantField
    private int accessMessageInMemoryMaxRatio = 40;
    // 是否開啓消息索引功能
    @ImportantField
    private boolean messageIndexEnable = true;
    private int maxHashSlotNum = 5000000;
    private int maxIndexNum = 5000000 * 4;
    private int maxMsgsNumBatch = 64;
    // 是否使用安全的消息索引功能,即可靠模式。
    // 可靠模式下,異常宕機恢復慢
    // 非可靠模式下,異常宕機恢復快
    @ImportantField
    private boolean messageIndexSafe = false;
    // HA功能
    private int haListenPort = 10912;
    private int haSendHeartbeatInterval = 1000 * 5;
    private int haHousekeepingInterval = 1000 * 20;
    private int haTransferBatchSize = 1024 * 32;
    // 如果不設置,則從NameServer獲取Master HA服務地址
    @ImportantField
    private String haMasterAddress = null;
    // Slave落後Master超過此值,則認爲存在異常
    private int haSlaveFallbehindMax = 1024 * 1024 * 256;
    @ImportantField
    private BrokerRole brokerRole = BrokerRole.ASYNC_MASTER;
    @ImportantField
    private FlushDiskType flushDiskType = FlushDiskType.ASYNC_FLUSH;
    // 同步刷盤超時時間
    private int syncFlushTimeout = 1000 * 5;
    // 定時消息相關
    private String messageDelayLevel = "1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h";
    private long flushDelayOffsetInterval = 1000 * 10;
    // 磁盤空間超過90%警戒水位,自動開始刪除文件
    @ImportantField
    private boolean cleanFileForciblyEnable = true;

  6,// 如果是slave,修改默認值
    if (BrokerRole.SLAVE == messageStoreConfig.getBrokerRole()) {
        int ratio = messageStoreConfig.getAccessMessageInMemoryMaxRatio() - 10;
        messageStoreConfig.setAccessMessageInMemoryMaxRatio(ratio);
     }

     如果是master broker命中消息在內存的最大比例是40

     如果是slave broker命中消息在內存的最大比例是30

  7,String namesrvAddr = brokerConfig.getNamesrvAddr();
            if (null != namesrvAddr) {
                try {
                    String[] addrArray = namesrvAddr.split(";");
                    if (addrArray != null) {
                        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);
                }
            }

     檢測Name Server地址設置是否正確 IP:PORT

  7,   switch (messageStoreConfig.getBrokerRole()) {
            case ASYNC_MASTER:
            case SYNC_MASTER:
                brokerConfig.setBrokerId(MixAll.MASTER_ID);
                break;
            case SLAVE:
                if (brokerConfig.getBrokerId() <= 0) {
                    System.out.println("Slave's brokerId must be > 0");
                    System.exit(-3);
                }

                break;
            default:
                break;
            }

      判斷如果是Master Broker Id必須是0 ,如果是Slave Broker Id必須大於0

  8,// Master監聽Slave請求的端口,默認爲服務端口+1
     messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);

    // 初始化Logback
    LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
    JoranConfigurator configurator = new JoranConfigurator();
    configurator.setContext(lc);
    lc.reset();
    configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/logback_broker.xml");
            log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName);

  9,final BrokerController controller = new BrokerController(
                brokerConfig,
                nettyServerConfig,
                nettyClientConfig,
                messageStoreConfig);

    初始化服務控制對象

        this.brokerConfig = brokerConfig; broker配置
        this.nettyServerConfig = nettyServerConfig;netty服務配置
        this.nettyClientConfig = nettyClientConfig;netty客戶端配置
        this.messageStoreConfig = messageStoreConfig;消息存儲配置
        this.consumerOffsetManager = new ConsumerOffsetManager(this);

        消費進度管理    

        this.topicConfigManager = new TopicConfigManager(this);

        Topic配置管理

        this.pullMessageProcessor = new PullMessageProcessor(this);

        拉消息請求處理

        this.pullRequestHoldService = new PullRequestHoldService(this);

        拉消息請求管理,如果拉不到消息,則在這裏Hold住,等待消息到來

        this.consumerIdsChangeListener = new DefaultConsumerIdsChangeListener(this);

        ConsumerId列表變化,通知所有Consumer

        this.consumerManager = new ConsumerManager(this.consumerIdsChangeListener);

        Consumer連接、訂閱關係管理

        this.producerManager = new ProducerManager();

        管理Producer組及各個Producer連接

        this.clientHousekeepingService = new ClientHousekeepingService(this);

        定期檢測客戶端連接,清除不活動的連接

        this.broker2Client = new Broker2Client(this);

        Broker主動調用客戶端接口

        this.subscriptionGroupManager = new SubscriptionGroupManager(this);

        用來管理訂閱組,包括訂閱權限等

        this.brokerOuterAPI = new BrokerOuterAPI(nettyClientConfig);

        Broker對外調用的API封裝

        this.filterServerManager = new FilterServerManager(this);
        過濾服務管理
        if (this.brokerConfig.getNamesrvAddr() != null) {
       this.brokerOuterAPI.updateNameServerAddressList(this.brokerConfig.getNamesrvAddr());
            log.info("user specfied name server address: {}",this.brokerConfig.getNamesrvAddr());
        }

        更新namesrv地址,防止存在存留數據
        this.slaveSynchronize = new SlaveSynchronize(this);

        Slave從Master同步信息(非消息)

        this.sendThreadPoolQueue =
                new LinkedBlockingQueue<Runnable>(this.brokerConfig.getSendThreadPoolQueueCapacity());

        初始化發送消息對應的線程池阻塞隊列size

        this.pullThreadPoolQueue =
                new LinkedBlockingQueue<Runnable>(this.brokerConfig.getPullThreadPoolQueueCapacity());

        初始化訂閱消息對應的線程池阻塞隊列size

        this.brokerStatsManager = new BrokerStatsManager(this.brokerConfig.getBrokerClusterName());

        broker 狀態管理
        this.setStoreHost(new InetSocketAddress(this.getBrokerConfig().getBrokerIP1(), this
            .getNettyServerConfig().getListenPort()));
        暫時沒發現在哪用,等用到了在說

  由於篇幅的問題 請看第三章註冊過程2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章