RocketMQ NameServer

版本: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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值