热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

RocketMQ源码分析之Broker(2)

来源:https://github.com/apache/rocketmq初始化BrokerControllerinitialize()首先加载四个配置文件,主

来源:https://github.com/apache/rocketmq


初始化


BrokerController


initialize()首先加载四个配置文件,主要是恢复以前的数据,当然第一次重启的话,这四个文件中也没有任何数据,他们主要是继承了ConfigManager类扩展了具体的文件存储方法以及编解码方法。初始化通信服务类,快速通信服务类监听端口为10909

    public boolean initialize() throws CloneNotSupportedException {
        boolean result = this.topicConfigManager.load();
    result = result && this.consumerOffsetManager.load();
    result = result && this.subscriptionGroupManager.load();
        result = result && this.consumerFilterManager.load();
    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);
    return result;
    }


    文件具体存储地方如下,每个文件存储的内容对象的具体属性可见上文。

      class BrokerPathConfigHelper 
      private static String brokerCOnfigPath= System.getProperty("user.home") + File.separator + "store"
          + File.separator + "config" + File.separator + "broker.properties";
      public static String getBrokerConfigPath() {
      return brokerConfigPath;
      }
      public static void setBrokerConfigPath(String path) {
      brokerCOnfigPath= path;
      }
      public static String getTopicConfigPath(final String rootDir) {
      return rootDir + File.separator + "config" + File.separator + "topics.json";
      }
      public static String getConsumerOffsetPath(final String rootDir) {
      return rootDir + File.separator + "config" + File.separator + "consumerOffset.json";
      }
      public static String getSubscriptionGroupPath(final String rootDir) {
      return rootDir + File.separator + "config" + File.separator + "subscriptionGroup.json";
      }
      public static String getConsumerFilterPath(final String rootDir) {
      return rootDir + File.separator + "config" + File.separator + "consumerFilter.json";
      }


      创建发送消息,拉取消息,查询消息,控制台命令接收消息,客户端链接管理,心跳消息,结束事务以及消费者管理这几个线程池,最后把code与线程以及处理类绑定到通信服务端处理请求。

        this.sendMessageExecutor = new BrokerFixedThreadPoolExecutor(
        this.brokerConfig.getSendMessageThreadPoolNums(),
        this.brokerConfig.getSendMessageThreadPoolNums(),
        1000 * 60,
        TimeUnit.MILLISECONDS,
        this.sendThreadPoolQueue,
        new ThreadFactoryImpl("SendMessageThread_"));


        this.pullMessageExecutor = new BrokerFixedThreadPoolExecutor(
        this.brokerConfig.getPullMessageThreadPoolNums(),
        this.brokerConfig.getPullMessageThreadPoolNums(),
        1000 * 60,
        TimeUnit.MILLISECONDS,
        this.pullThreadPoolQueue,
        new ThreadFactoryImpl("PullMessageThread_"));


        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_"));


        public void registerProcessor() {


        SendMessageProcessor sendProcessor = new SendMessageProcessor(this);
        sendProcessor.registerSendMessageHook(sendMessageHookList);
        sendProcessor.registerConsumeMessageHook(consumeMessageHookList);


        this.remotingServer.registerProcessor(RequestCode.SEND_MESSAGE, sendProcessor, this.sendMessageExecutor);
        this.remotingServer.registerProcessor(RequestCode.SEND_MESSAGE_V2, sendProcessor, this.sendMessageExecutor);
        this.remotingServer.registerProcessor(RequestCode.SEND_BATCH_MESSAGE, sendProcessor, this.sendMessageExecutor);
        this.remotingServer.registerProcessor(RequestCode.CONSUMER_SEND_MSG_BACK, sendProcessor, this.sendMessageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.SEND_MESSAGE, sendProcessor, this.sendMessageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.SEND_MESSAGE_V2, sendProcessor, this.sendMessageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.SEND_BATCH_MESSAGE, sendProcessor, this.sendMessageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.CONSUMER_SEND_MSG_BACK, sendProcessor, this.sendMessageExecutor);


        this.remotingServer.registerProcessor(RequestCode.PULL_MESSAGE, this.pullMessageProcessor, this.pullMessageExecutor);
        this.pullMessageProcessor.registerConsumeMessageHook(consumeMessageHookList);


        NettyRequestProcessor queryProcessor = new QueryMessageProcessor(this);
        this.remotingServer.registerProcessor(RequestCode.QUERY_MESSAGE, queryProcessor, this.queryMessageExecutor);
        this.remotingServer.registerProcessor(RequestCode.VIEW_MESSAGE_BY_ID, queryProcessor, this.queryMessageExecutor);


        this.fastRemotingServer.registerProcessor(RequestCode.QUERY_MESSAGE, queryProcessor, this.queryMessageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.VIEW_MESSAGE_BY_ID, queryProcessor, this.queryMessageExecutor);


        ClientManageProcessor clientProcessor = new ClientManageProcessor(this);
        this.remotingServer.registerProcessor(RequestCode.HEART_BEAT, clientProcessor, this.heartbeatExecutor);
        this.remotingServer.registerProcessor(RequestCode.UNREGISTER_CLIENT, clientProcessor, this.clientManageExecutor);
        this.remotingServer.registerProcessor(RequestCode.CHECK_CLIENT_CONFIG, clientProcessor, this.clientManageExecutor);


        this.fastRemotingServer.registerProcessor(RequestCode.HEART_BEAT, clientProcessor, this.heartbeatExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.UNREGISTER_CLIENT, clientProcessor, this.clientManageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.CHECK_CLIENT_CONFIG, clientProcessor, this.clientManageExecutor);


        ConsumerManageProcessor cOnsumerManageProcessor= new ConsumerManageProcessor(this);
        this.remotingServer.registerProcessor(RequestCode.GET_CONSUMER_LIST_BY_GROUP, consumerManageProcessor, this.consumerManageExecutor);
        this.remotingServer.registerProcessor(RequestCode.UPDATE_CONSUMER_OFFSET, consumerManageProcessor, this.consumerManageExecutor);
        this.remotingServer.registerProcessor(RequestCode.QUERY_CONSUMER_OFFSET, consumerManageProcessor, this.consumerManageExecutor);


        this.fastRemotingServer.registerProcessor(RequestCode.GET_CONSUMER_LIST_BY_GROUP, consumerManageProcessor, this.consumerManageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.UPDATE_CONSUMER_OFFSET, consumerManageProcessor, this.consumerManageExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.QUERY_CONSUMER_OFFSET, consumerManageProcessor, this.consumerManageExecutor);


        this.remotingServer.registerProcessor(RequestCode.END_TRANSACTION, new EndTransactionProcessor(this), this.endTransactionExecutor);
        this.fastRemotingServer.registerProcessor(RequestCode.END_TRANSACTION, new EndTransactionProcessor(this), this.endTransactionExecutor);


        AdminBrokerProcessor adminProcessor = new AdminBrokerProcessor(this);
        this.remotingServer.registerDefaultProcessor(adminProcessor, this.adminBrokerExecutor);
        this.fastRemotingServer.registerDefaultProcessor(adminProcessor, this.adminBrokerExecutor);
        }


        BrokerStats定时程序打印每天的消息量

          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);


          public void record() {
          this.msgPutTotalYesterdayMorning = this.msgPutTotalTodayMorning;
          this.msgGetTotalYesterdayMorning = this.msgGetTotalTodayMorning;


          this.msgPutTotalTodayMorning =
          this.defaultMessageStore.getStoreStatsService().getPutMessageTimesTotal();
          this.msgGetTotalTodayMorning =
          this.defaultMessageStore.getStoreStatsService().getGetMessageTransferedMsgCount().get();


          log.info("yesterday put message total: {}", msgPutTotalTodayMorning - msgPutTotalYesterdayMorning);
          log.info("yesterday get message total: {}", msgGetTotalTodayMorning - msgGetTotalYesterdayMorning);
          }


          定时持久化ConsumerOffsetManager和ConsumerFilterManager里的数据

            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);


            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);


            protectBroker方法主要是当disableConsumeIfConsumerReadSlowly开启时定时检查当前消费组消费消息的进度,超过consumerFallbehindThreshold = 1024L * 1024 * 1024 * 16配置的大小后会剔除掉该订阅组,停止消费消息用来保护broker,因为存储消息的commitLog一个文件大小才为1024L * 1024 * 1024。

              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);


              public void protectBroker() {
              if (this.brokerConfig.isDisableConsumeIfConsumerReadSlowly()) {
              final Iterator> it = this.brokerStatsManager.getMomentStatsItemSetFallSize().getStatsItemTable().entrySet().iterator();
              while (it.hasNext()) {
              final Map.Entry next = it.next();
              final long fallBehindBytes = next.getValue().getValue().get();
              if (fallBehindBytes > this.brokerConfig.getConsumerFallbehindThreshold()) {
              final String[] split = next.getValue().getStatsKey().split("@");
              final String group = split[2];
              LOG_PROTECTION.info("[PROTECT_BROKER] the consumer[{}] consume slowly, {} bytes, disable it", group, fallBehindBytes);
              this.subscriptionGroupManager.disableConsume(group);
              }
              }
              }
              }


              printWaterMark方法主要是打印各个队列的任务大小以及最早的放入时间

                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);


                dispatchBehindBytes方法主要是打印目前最新的消息偏移量和已经分发给消费队列以及索引创建服务之间的差距。

                  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);


                  public long behind() {
                  return DefaultMessageStore.this.commitLog.getMaxOffset() - this.reputFromOffset;
                  }


                  更新配置中心命名服务的地址信息,一个是从broker配置中获取,另一个是从配置的url中获取,官方推荐后者,因为可以动态更改配置信息,

                    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);
                    }


                    TopAddressing topAddressing = new TopAddressing(MixAll.getWSAddr());


                    public static String getWSAddr() {
                    String wsDomainName = System.getProperty("rocketmq.namesrv.domain", DEFAULT_NAMESRV_ADDR_LOOKUP);
                    String wsDomainSubgroup = System.getProperty("rocketmq.namesrv.domain.subgroup", "nsaddr");
                    String wsAddr = "http://" + wsDomainName + ":8080/rocketmq/" + wsDomainSubgroup;
                    if (wsDomainName.indexOf(":") > 0) {
                    wsAddr = "http://" + wsDomainName + "/rocketmq/" + wsDomainSubgroup;
                    }
                    return wsAddr;
                    }


                    当broker为SLAVE时,更新主broker的地址以便进行同步操作,主要同步topic信息,消费偏移量,延迟队列偏移量,以及订阅组信息,这些主要用于消费端从该从broker拉取消息时使用。主broker只打印双方消息的偏移量差距。

                      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);
                      }
                      }
                      }, 1000 * 10, 1000 * 60, TimeUnit.MILLISECONDS);
                      } 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);
                      }


                      public void syncAll() {
                      this.syncTopicConfig();
                      this.syncConsumerOffset();
                      this.syncDelayOffset();
                      this.syncSubscriptionGroupConfig();
                      }




                      推荐阅读
                      author-avatar
                      chroalist
                      这个家伙很懒,什么也没留下!
                      PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
                      Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有