版本:4.2.0,源码:class文件
NameServer启动源码分析:
NameServer通过main方法启动
public static void main(String[] args) { main0(args); }
public static NamesrvController main0(String[] args) { System.setProperty("rocketmq.remoting.version", Integer.toString(MQVersion.CURRENT_VERSION)); try { Options options = ServerUtil.buildCommandlineOptions(new Options()); commandLine = ServerUtil.parseCmdLine("mqnamesrv", args, buildCommandlineOptions(options), new PosixParser()); if (null == commandLine) { System.exit(-1); return null; } else { 。。。 // 加载日志相关 LoggerContext lc = (LoggerContext)LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(lc); lc.reset(); configurator.doConfigure(namesrvConfig.getRocketmqHome() + "/conf/logback_namesrv.xml"); Logger log = LoggerFactory.getLogger("RocketmqNamesrv"); MixAll.printObjectProperties(log, namesrvConfig); MixAll.printObjectProperties(log, nettyServerConfig); // 创建NamesrvController final NamesrvController controller = new NamesrvController(namesrvConfig, nettyServerConfig); controller.getConfiguration().registerConfig(properties); // 初始化NamesrvController boolean initResult = controller.initialize(); if (!initResult) { controller.shutdown(); System.exit(-3); } Runtime.getRuntime().addShutdownHook(new ShutdownHookThread(log, new Callable<Void>() { public Void call() throws Exception { controller.shutdown(); return null; } })); // 启动NamesrvController controller.start(); String tip = "The Name Server boot success. serializeType=" + RemotingCommand.getSerializeTypeConfigInThisServer(); log.info(tip); System.out.printf(tip + "%n"); return controller; } } catch (Throwable var10) { var10.printStackTrace(); System.exit(-1); return null; } }
初始化NamesrvController
public boolean initialize() { // 加载配置,从文件到内存 this.kvConfigManager.load(); // 创建netty服务 this.remotingServer = new NettyRemotingServer(this.nettyServerConfig, this.brokerHousekeepingService); // 线程池,处理netty连接 this.remotingExecutor = Executors.newFixedThreadPool(this.nettyServerConfig.getServerWorkerThreads(), new ThreadFactoryImpl("RemotingExecutorThread_")); // 注册处理器 this.registerProcessor(); this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { public void run() { // 扫描超时的broker NamesrvController.this.routeInfoManager.scanNotActiveBroker(); } }, 5L, 10L, TimeUnit.SECONDS); this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { public void run() { // 打印配置 NamesrvController.this.kvConfigManager.printAllPeriodically(); } }, 1L, 10L, TimeUnit.MINUTES); return true; }
registerProcessor
private void registerProcessor() { if (this.namesrvConfig.isClusterTest()) { this.remotingServer.registerDefaultProcessor(new ClusterTestRequestProcessor(this, this.namesrvConfig.getProductEnvName()), this.remotingExecutor); } else { // 默认注册的是DefaultRequestProcessor,DefaultRequestProcessor包含了重要的几个方法: // 注册broker,获取topic路由信息,...等等 this.remotingServer.registerDefaultProcessor(new DefaultRequestProcessor(this), this.remotingExecutor); } }
启动NamesrvController
public void start() throws Exception { // 启动netty服务 this.remotingServer.start(); }
注册broker
先看看broker如何发送注册信息,相关源码参考BrokerController.start()
public void start() throws Exception { ... // 服务启动时就注册 this.registerBrokerAll(true, false); // 定时注册,30秒一次 this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { public void run() { try { BrokerController.this.registerBrokerAll(true, false); } catch (Throwable var2) { BrokerController.log.error("registerBrokerAll Exception", var2); } } }, 10000L, 30000L, TimeUnit.MILLISECONDS); ... }
public synchronized void registerBrokerAll(boolean checkOrderConfig, boolean oneway) { TopicConfigSerializeWrapper topicConfigWrapper = this.getTopicConfigManager().buildTopicConfigSerializeWrapper(); if (!PermName.isWriteable(this.getBrokerConfig().getBrokerPermission()) || !PermName.isReadable(this.getBrokerConfig().getBrokerPermission())) { ConcurrentHashMap<String, TopicConfig> topicConfigTable = new ConcurrentHashMap(); Iterator i$ = topicConfigWrapper.getTopicConfigTable().values().iterator(); while(i$.hasNext()) { TopicConfig topicConfig = (TopicConfig)i$.next(); TopicConfig tmp = new TopicConfig(topicConfig.getTopicName(), topicConfig.getReadQueueNums(), topicConfig.getWriteQueueNums(), this.brokerConfig.getBrokerPermission()); topicConfigTable.put(topicConfig.getTopicName(), tmp); } topicConfigWrapper.setTopicConfigTable(topicConfigTable); } // 注册信息包括:topic,readQueueNums,writeQueueNums,broker权限 RegisterBrokerResult registerBrokerResult = this.brokerOuterAPI.registerBrokerAll(this.brokerConfig.getBrokerClusterName(), this.getBrokerAddr(), this.brokerConfig.getBrokerName(), this.brokerConfig.getBrokerId(), this.getHAServerAddr(), topicConfigWrapper, this.filterServerManager.buildNewFilterServerList(), oneway, this.brokerConfig.getRegisterBrokerTimeoutMills()); 。。。 }
BrokerOuterAPI
public RegisterBrokerResult registerBrokerAll(String clusterName, String brokerAddr, String brokerName, long brokerId, String haServerAddr, TopicConfigSerializeWrapper topicConfigWrapper, List<String> filterServerList, boolean oneway, int timeoutMills) { RegisterBrokerResult registerBrokerResult = null; List<String> nameServerAddressList = this.remotingClient.getNameServerAddressList(); if (nameServerAddressList != null) { Iterator i$ = nameServerAddressList.iterator(); while(i$.hasNext()) { String namesrvAddr = (String)i$.next(); try { // 发送注册请求 RegisterBrokerResult result = this.registerBroker(namesrvAddr, clusterName, brokerAddr, brokerName, brokerId, haServerAddr, topicConfigWrapper, filterServerList, oneway, timeoutMills); if (result != null) { registerBrokerResult = result; } log.info("register broker to name server {} OK", namesrvAddr); } catch (Exception var16) { log.warn("registerBroker Exception, {}", namesrvAddr, var16); } } } return registerBrokerResult; }
private RegisterBrokerResult registerBroker(String namesrvAddr, String clusterName, String brokerAddr, String brokerName, long brokerId, String haServerAddr, TopicConfigSerializeWrapper topicConfigWrapper, List<String> filterServerList, boolean oneway, int timeoutMills) throws RemotingCommandException, MQBrokerException, RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException, InterruptedException { RegisterBrokerRequestHeader requestHeader = new RegisterBrokerRequestHeader(); requestHeader.setBrokerAddr(brokerAddr); requestHeader.setBrokerId(brokerId); requestHeader.setBrokerName(brokerName); requestHeader.setClusterName(clusterName); requestHeader.setHaServerAddr(haServerAddr); RemotingCommand request = RemotingCommand.createRequestCommand(103, requestHeader); 。。。 }
可以看到发送的对应的code时103,下面就去nameServer看看103对应的方法
DefaultRequestProcessor
public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { if (log.isDebugEnabled()) { log.debug("receive request, {} {} {}", new Object[]{request.getCode(), RemotingHelper.parseChannelRemoteAddr(ctx.channel()), request}); } switch(request.getCode()) { 。。。 case 103: Version brokerVersion = MQVersion.value2Version(request.getVersion()); if (brokerVersion.ordinal() >= Version.V3_0_11.ordinal()) { return this.registerBrokerWithFilterServer(ctx, request); } // 注册broker return this.registerBroker(ctx, request); case 104: return this.unregisterBroker(ctx, request); case 105: // 获取topic路由信息 return this.getRouteInfoByTopic(ctx, request); 。。。 } }
public RemotingCommand registerBrokerWithFilterServer(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { 。。。 RegisterBrokerResult result = this.namesrvController.getRouteInfoManager().registerBroker(requestHeader.getClusterName(), requestHeader.getBrokerAddr(), requestHeader.getBrokerName(), requestHeader.getBrokerId(), requestHeader.getHaServerAddr(), registerBrokerBody.getTopicConfigSerializeWrapper(), registerBrokerBody.getFilterServerList(), ctx.channel()); 。。。 }
RouteInfoManager
public RegisterBrokerResult registerBroker(String clusterName, String brokerAddr, String brokerName, long brokerId, String haServerAddr, TopicConfigSerializeWrapper topicConfigWrapper, List<String> filterServerList, Channel channel) { RegisterBrokerResult result = new RegisterBrokerResult(); try { try { this.lock.writeLock().lockInterruptibly(); // 缓存集群相关信息 Set<String> brokerNames = (Set)this.clusterAddrTable.get(clusterName); if (null == brokerNames) { brokerNames = new HashSet(); this.clusterAddrTable.put(clusterName, brokerNames); } ((Set)brokerNames).add(brokerName); boolean registerFirst = false; // 缓存broker地址 BrokerData brokerData = (BrokerData)this.brokerAddrTable.get(brokerName); if (null == brokerData) { registerFirst = true; brokerData = new BrokerData(clusterName, brokerName, new HashMap()); this.brokerAddrTable.put(brokerName, brokerData); } String oldAddr = (String)brokerData.getBrokerAddrs().put(brokerId, brokerAddr); registerFirst = registerFirst || null == oldAddr; if (null != topicConfigWrapper && 0L == brokerId && (this.isBrokerTopicConfigChanged(brokerAddr, topicConfigWrapper.getDataVersion()) || registerFirst)) { ConcurrentMap<String, TopicConfig> tcTable = topicConfigWrapper.getTopicConfigTable(); if (tcTable != null) { Iterator i$ = tcTable.entrySet().iterator(); // 缓存queue信息 while(i$.hasNext()) { Entry<String, TopicConfig> entry = (Entry)i$.next(); this.createAndUpdateQueueData(brokerName, (TopicConfig)entry.getValue()); } } } // brokerLiveTable保存存活的broker BrokerLiveInfo prevBrokerLiveInfo = (BrokerLiveInfo)this.brokerLiveTable.put(brokerAddr, new BrokerLiveInfo(System.currentTimeMillis(), topicConfigWrapper.getDataVersion(), channel, haServerAddr)); if (null == prevBrokerLiveInfo) { log.info("new broker registered, {} HAServer: {}", brokerAddr, haServerAddr); } // 缓存filterServer if (filterServerList != null) { if (filterServerList.isEmpty()) { this.filterServerTable.remove(brokerAddr); } else { this.filterServerTable.put(brokerAddr, filterServerList); } } if (0L != brokerId) { String masterAddr = (String)brokerData.getBrokerAddrs().get(0L); if (masterAddr != null) { BrokerLiveInfo brokerLiveInfo = (BrokerLiveInfo)this.brokerLiveTable.get(masterAddr); if (brokerLiveInfo != null) { result.setHaServerAddr(brokerLiveInfo.getHaServerAddr()); result.setMasterAddr(masterAddr); } } } } finally { this.lock.writeLock().unlock(); } } catch (Exception var22) { log.error("registerBroker Exception", var22); } return result; }
缓存queue信息
private void createAndUpdateQueueData(String brokerName, TopicConfig topicConfig) { QueueData queueData = new QueueData(); queueData.setBrokerName(brokerName); queueData.setWriteQueueNums(topicConfig.getWriteQueueNums()); queueData.setReadQueueNums(topicConfig.getReadQueueNums()); queueData.setPerm(topicConfig.getPerm()); queueData.setTopicSynFlag(topicConfig.getTopicSysFlag()); List<QueueData> queueDataList = (List)this.topicQueueTable.get(topicConfig.getTopicName()); if (null == queueDataList) { List<QueueData> queueDataList = new LinkedList(); queueDataList.add(queueData); this.topicQueueTable.put(topicConfig.getTopicName(), queueDataList); log.info("new topic registered, {} {}", topicConfig.getTopicName(), queueData); } else { 。。。 } }
总结:broker注册主要是更新nameServer的
topicQueueTable
brokerAddrTable
clusterAddrTable
brokerLiveTable
filterServerTable
topic路由信息
直接看105对应的方法,客户端如何发起请求可以看producer和consumer的相关启动代码
public RemotingCommand getRouteInfoByTopic(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { 。。。 TopicRouteData topicRouteData = this.namesrvController.getRouteInfoManager().pickupTopicRouteData(requestHeader.getTopic()); 。。。 }
public TopicRouteData pickupTopicRouteData(String topic) { TopicRouteData topicRouteData = new TopicRouteData(); boolean foundQueueData = false; boolean foundBrokerData = false; Set<String> brokerNameSet = new HashSet(); List<BrokerData> brokerDataList = new LinkedList(); topicRouteData.setBrokerDatas(brokerDataList); HashMap<String, List<String>> filterServerMap = new HashMap(); topicRouteData.setFilterServerTable(filterServerMap); try { try { this.lock.readLock().lockInterruptibly(); List<QueueData> queueDataList = (List)this.topicQueueTable.get(topic); if (queueDataList != null) { topicRouteData.setQueueDatas(queueDataList); foundQueueData = true; Iterator it = queueDataList.iterator(); while(it.hasNext()) { QueueData qd = (QueueData)it.next(); brokerNameSet.add(qd.getBrokerName()); } Iterator i$ = brokerNameSet.iterator(); label104: while(true) { BrokerData brokerData; do { if (!i$.hasNext()) { break label104; } String brokerName = (String)i$.next(); brokerData = (BrokerData)this.brokerAddrTable.get(brokerName); } while(null == brokerData); BrokerData brokerDataClone = new BrokerData(brokerData.getCluster(), brokerData.getBrokerName(), (HashMap)brokerData.getBrokerAddrs().clone()); brokerDataList.add(brokerDataClone); foundBrokerData = true; Iterator i$ = brokerDataClone.getBrokerAddrs().values().iterator(); while(i$.hasNext()) { String brokerAddr = (String)i$.next(); List<String> filterServerList = (List)this.filterServerTable.get(brokerAddr); filterServerMap.put(brokerAddr, filterServerList); } } } } finally { this.lock.readLock().unlock(); } } catch (Exception var21) { log.error("pickupTopicRouteData Exception", var21); } if (log.isDebugEnabled()) { log.debug("pickupTopicRouteData {} {}", topic, topicRouteData); } return foundBrokerData && foundQueueData ? topicRouteData : null; }
总结:topic路由信息主要是由topicQueueTable和brokerAddrTable相关信息组装成的topicRouteData