RocketMQ源码解析——Broker

目录:

1. 源码解析:

首先找到Broker启动入口:

public static void main(String[] args) {
    start(createBrokerController(args)); // 创建Broker控制器,并启动
}
  • 创建Broker控制器:

可能有人会好奇,为了是创建Broker控制器呢?因为在开发的角度,控制器Controller通常是用于接收并处理外部传入的请求。而正是这个原因,Broker需要接受来自消息生产者的消息发送请求,和对消费者进行消息拉取请求,所以才将Broker看做是一个Controller

为了更好的理解源码中的代码执行逻辑,因此先上一图,大致了解Broker控制器的创建流程:

在这里插入图片描述
根据上图,我们再实际结合代码来进行解析:

- 创建控制器:

public static BrokerController createBrokerController(String[] args) {
    System.setProperty(RemotingCommand.REMOTING_VERSION_KEY, Integer.toString(MQVersion.CURRENT_VERSION)); // 设置RocketMQ版本属性信息

    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 {
        Options options = ServerUtil.buildCommandlineOptions(new Options());
        commandLine = ServerUtil.parseCmdLine("mqbroker", args, buildCommandlineOptions(options), new PosixParser()); // 解析命令执行对象
        if (null == commandLine) {
            System.exit(-1);
        }

        final BrokerConfig brokerConfig = new BrokerConfig(); // 创建Broker配置对象
        final NettyServerConfig nettyServerConfig = new NettyServerConfig(); // 创建Netty服务器端配置对象,用于接收请求
        final NettyClientConfig nettyClientConfig = new NettyClientConfig(); // 创建Netty客户端配置对象,用于发送请求

        nettyClientConfig.setUseTLS(Boolean.parseBoolean(System.getProperty(TLS_ENABLE, String.valueOf(TlsSystemConfig.tlsMode == TlsMode.ENFORCING))));
        nettyServerConfig.setListenPort(10911); // 服务端默认监听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);

                BrokerPathConfigHelper.setBrokerConfigPath(file);
                in.close();
            }
        }

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

        String namesrvAddr = brokerConfig.getNamesrvAddr(); // 获取NameServer的地址
        if (null != namesrvAddr) {
            try {
                String[] addrArray = namesrvAddr.split(";"); // 如果是NameServer是多结点集群模式,则每个地址用分号隔开
                for (String addr : addrArray) {
                    RemotingUtil.string2SocketAddress(addr); // 与NameServer创建长连接通道
                }
            } 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()) {
			// 若当前的Broker属于同步/异步主结点,则设置id为0(即主结点id为0)
            case ASYNC_MASTER: 
            case SYNC_MASTER:
                brokerConfig.setBrokerId(MixAll.MASTER_ID); // MixAll.MASTER_ID = 0
                break;
            // 若当前的Broker属于从结点,则id只能大于0
            case SLAVE:
                if (brokerConfig.getBrokerId() <= 0) {
                    System.out.printf("Slave's brokerId must be > 0");
                    System.exit(-3);
                }
                break;
            default:
                break;
        }

        if (messageStoreConfig.isEnableDLegerCommitLog()) {
            brokerConfig.setBrokerId(-1);
        }

        messageStoreConfig.setHaListenPort(nettyServerConfig.getListenPort() + 1);
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        JoranConfigurator configurator = new JoranConfigurator();
        configurator.setContext(lc);
        lc.reset();
        configurator.doConfigure(brokerConfig.getRocketmqHome() + "/conf/logback_broker.xml");
		
		// 处理命令中启动-p参数
        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')) {  // 处理命令中启动-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);

        final BrokerController controller = new BrokerController(brokerConfig, nettyServerConfig, nettyClientConfig, messageStoreConfig); // 依赖配置对象创建控制器

        controller.getConfiguration().registerConfig(properties);

        boolean initResult = controller.initialize(); // 控制器初始化
        if (!initResult) { // 控制器初始化失败
            controller.shutdown(); // 关闭控制器
            System.exit(-3);
        }

        Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { // 为JVM绑定程序关闭钩子函数
            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;
}

- 启动控制器:

public static BrokerController start(BrokerController controller) {
    try {
        controller.start(); // 核心方法,启动控制器

        String tip = "The broker[" + controller.getBrokerConfig().getBrokerName() + ", "
            + controller.getBrokerAddr() + "] boot success. serializeType=" + RemotingCommand.getSerializeTypeConfigInThisServer();

        if (null != controller.getBrokerConfig().getNamesrvAddr()) {
            tip += " and name server is " + controller.getBrokerConfig().getNamesrvAddr();
        }

        log.info(tip);
        System.out.printf("%s%n", tip);
        return controller;
    } catch (Throwable e) {
        e.printStackTrace();
        System.exit(-1);
    }

    return null;
}
  • 控制器启动,关注核心方法:
public void start() throws Exception {
	...
    this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() { // 等待10s后,每间隔指定时间(自定义向NameServer上报注册信息时间,或者默认60s)向NameServer发送一次心跳请求,上报Broker信息
        @Override
        public void run() {
            try {
                BrokerController.this.registerBrokerAll(true, false, brokerConfig.isForceRegister());
            } catch (Throwable e) {
                log.error("registerBrokerAll Exception", e);
            }
        }
    }, 1000 * 10, Math.max(10000, Math.min(brokerConfig.getRegisterNameServerPeriod(), 60000)), TimeUnit.MILLISECONDS);
	...
}
  • 向NameServer发送心跳请求,上报Broker信息:
public synchronized void registerBrokerAll(final boolean checkOrderConfig, boolean oneway, boolean forceRegister) {
    TopicConfigSerializeWrapper topicConfigWrapper = this.getTopicConfigManager().buildTopicConfigSerializeWrapper();
	... 
    if (forceRegister || needRegister(this.brokerConfig.getBrokerClusterName(),
        this.getBrokerAddr(),
        this.brokerConfig.getBrokerName(),
        this.brokerConfig.getBrokerId(),
        this.brokerConfig.getRegisterBrokerTimeoutMills())) { // forceRegister默认为true,即启动Broker控制器都需要向NameServer注册信息
        doRegisterBrokerAll(checkOrderConfig, oneway, topicConfigWrapper); // 注册上报Broker信息
    }
}
private void doRegisterBrokerAll(boolean checkOrderConfig, boolean oneway, TopicConfigSerializeWrapper topicConfigWrapper) {
    List<RegisterBrokerResult> registerBrokerResultList = this.brokerOuterAPI.registerBrokerAll(
        this.brokerConfig.getBrokerClusterName(),
        this.getBrokerAddr(),
        this.brokerConfig.getBrokerName(),
        this.brokerConfig.getBrokerId(),
        this.getHAServerAddr(),
        topicConfigWrapper,
        this.filterServerManager.buildNewFilterServerList(),
        oneway,
        this.brokerConfig.getRegisterBrokerTimeoutMills(),
        this.brokerConfig.isCompressedRegister()); // 发送注册请求,上报Broker信息, 
	// 根据注册响应结果,更新信息
    if (registerBrokerResultList.size() > 0) {
        RegisterBrokerResult registerBrokerResult = registerBrokerResultList.get(0);
        if (registerBrokerResult != null) {
            if (this.updateMasterHAServerAddrPeriodically && registerBrokerResult.getHaServerAddr() != null) {
                this.messageStore.updateHaMasterAddress(registerBrokerResult.getHaServerAddr());
            }

            this.slaveSynchronize.setMasterAddr(registerBrokerResult.getMasterAddr());

            if (checkOrderConfig) {
                this.getTopicConfigManager().updateOrderTopicConfig(registerBrokerResult.getKvTable());
            }
        }
    }
}
  • 向NameServer发送注册请求,上报Broker信息:
public List<RegisterBrokerResult> registerBrokerAll(
    final String clusterName,
    final String brokerAddr,
    final String brokerName,
    final long brokerId,
    final String haServerAddr,
    final TopicConfigSerializeWrapper topicConfigWrapper,
    final List<String> filterServerList,
    final boolean oneway,
    final int timeoutMills,
    final boolean compressed) {

    final List<RegisterBrokerResult> registerBrokerResultList = new CopyOnWriteArrayList<>();
    List<String> nameServerAddressList = this.remotingClient.getNameServerAddressList();
    if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
		// 创建并封装请求头
        final RegisterBrokerRequestHeader requestHeader = new RegisterBrokerRequestHeader(); 
        requestHeader.setBrokerAddr(brokerAddr); 
        requestHeader.setBrokerId(brokerId); 
        requestHeader.setBrokerName(brokerName);
        requestHeader.setClusterName(clusterName);
        requestHeader.setHaServerAddr(haServerAddr);
        requestHeader.setCompressed(compressed);
		// 创建并封装请求体
        RegisterBrokerBody requestBody = new RegisterBrokerBody();
        requestBody.setTopicConfigSerializeWrapper(topicConfigWrapper);
        requestBody.setFilterServerList(filterServerList);
        final byte[] body = requestBody.encode(compressed);
        final int bodyCrc32 = UtilAll.crc32(body);
        requestHeader.setBodyCrc32(bodyCrc32);
        final CountDownLatch countDownLatch = new CountDownLatch(nameServerAddressList.size());
        for (final String namesrvAddr : nameServerAddressList) { // 遍历NameServer地址(集群)
            brokerOuterExecutor.execute(new Runnable() { // 通过线程池执行任务
                @Override
                public void run() {
                    try {
                        RegisterBrokerResult result = registerBroker(namesrvAddr, oneway, timeoutMills, requestHeader, body); // 发送请求注册Broker信息
                        if (result != null) {
                            registerBrokerResultList.add(result); // 收集注册结果
                        }

                        log.info("register broker[{}]to name server {} OK", brokerId, namesrvAddr);
                    } catch (Exception e) {
                        log.warn("registerBroker Exception, {}", namesrvAddr, e);
                    } finally {
                        countDownLatch.countDown();
                    }
                }
            });
        }

        try {
            countDownLatch.await(timeoutMills, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
        }
    }

    return registerBrokerResultList;
}
private RegisterBrokerResult registerBroker(final String namesrvAddr, final boolean oneway, final int timeoutMills, final RegisterBrokerRequestHeader requestHeader, final byte[] body) throws RemotingCommandException, MQBrokerException, RemotingConnectException, RemotingSendRequestException, RemotingTimeoutException,InterruptedException {
    RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.REGISTER_BROKER, requestHeader); // 创建Broker注册专属请求头
    request.setBody(body); // 添加请求体

    if (oneway) { // 判断是否属于单向请求(即无响应结果,初始启动默认为false)
        try {
            this.remotingClient.invokeOneway(namesrvAddr, request, timeoutMills); // 发送单向请求注册Broker,无须等待响应结果。效率更高,但不保证请求成功
        } catch (RemotingTooMuchRequestException e) {
            // Ignore
        }
        return null;
    }

    RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, timeoutMills); // 发送同步请求,并等待获取响应结果
    assert response != null;
    switch (response.getCode()) { // 判断响应结果
        case ResponseCode.SUCCESS: { // 响应结果为注册Broker信息成功,并封装响应数据
            RegisterBrokerResponseHeader responseHeader = (RegisterBrokerResponseHeader) response.decodeCommandCustomHeader(RegisterBrokerResponseHeader.class);
            RegisterBrokerResult result = new RegisterBrokerResult();
            result.setMasterAddr(responseHeader.getMasterAddr());
            result.setHaServerAddr(responseHeader.getHaServerAddr());
            if (response.getBody() != null) {
                result.setKvTable(KVTable.decode(response.getBody(), KVTable.class));
            }
            return result;// 返回响应封装结果
        }
        default:
            break;
    }

    throw new MQBrokerException(response.getCode(), response.getRemark(), requestHeader == null ? null : requestHeader.getBrokerAddr()); // 注册信息失败,抛出异常
}

以上逻辑就是Broker发送请求,向NameServer注册自己的信息,以及封装保存响应结果。
还有一个问题:请求是发过去了,那NameServer如何接收请求?又是如何对请求中的Broker信息的进行处理?

针对上面两个疑问,首先大致了解其中的执行流程,如下图所示:
在这里插入图片描述
通过上面的时序图,可以发现其中主要涉及到的类有DefaultRequestProcessor、RouteInfoManager
其中DefaultRequestProcessor是用做处理请求,而RoutInfoManager则是存储并管理路由信息,因此想了解NameServer是如何处理Broker注册请求,首先来看DefaultRequestProcessor类中的processRequest方法:

public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    if (ctx != null) {
        log.debug("receive request, {} {} {}",
            request.getCode(),
            RemotingHelper.parseChannelRemoteAddr(ctx.channel()),
            request);
    }
    // 判断请求类型
    switch (request.getCode()) {
        case RequestCode.PUT_KV_CONFIG:
            return this.putKVConfig(ctx, request);
        case RequestCode.GET_KV_CONFIG:
            return this.getKVConfig(ctx, request);
        case RequestCode.DELETE_KV_CONFIG:
            return this.deleteKVConfig(ctx, request);
        case RequestCode.QUERY_DATA_VERSION:
            return queryBrokerTopicConfig(ctx, request);
        case RequestCode.REGISTER_BROKER: // 重点关注,Broker注册请求
            Version brokerVersion = MQVersion.value2Version(request.getVersion());
            if (brokerVersion.ordinal() >= MQVersion.Version.V3_0_11.ordinal()) { // 当前RocketMQ版本大于3.0版本
                return this.registerBrokerWithFilterServer(ctx, request); // 注册Broker信息
            } else { // 小于3.0版本
                return this.registerBroker(ctx, request); // 注册Broker信息
            }
        case RequestCode.UNREGISTER_BROKER:
            return this.unregisterBroker(ctx, request);
        case RequestCode.GET_ROUTEINFO_BY_TOPIC:
            return this.getRouteInfoByTopic(ctx, request);
        case RequestCode.GET_BROKER_CLUSTER_INFO:
            return this.getBrokerClusterInfo(ctx, request);
        case RequestCode.WIPE_WRITE_PERM_OF_BROKER:
            return this.wipeWritePermOfBroker(ctx, request);
        case RequestCode.GET_ALL_TOPIC_LIST_FROM_NAMESERVER:
            return getAllTopicListFromNameserver(ctx, request);
        case RequestCode.DELETE_TOPIC_IN_NAMESRV:
            return deleteTopicInNamesrv(ctx, request);
        case RequestCode.GET_KVLIST_BY_NAMESPACE:
            return this.getKVListByNamespace(ctx, request);
        case RequestCode.GET_TOPICS_BY_CLUSTER:
            return this.getTopicsByCluster(ctx, request);
        case RequestCode.GET_SYSTEM_TOPIC_LIST_FROM_NS:
            return this.getSystemTopicListFromNs(ctx, request);
        case RequestCode.GET_UNIT_TOPIC_LIST:
            return this.getUnitTopicList(ctx, request);
        case RequestCode.GET_HAS_UNIT_SUB_TOPIC_LIST:
            return this.getHasUnitSubTopicList(ctx, request);
        case RequestCode.GET_HAS_UNIT_SUB_UNUNIT_TOPIC_LIST:
            return this.getHasUnitSubUnUnitTopicList(ctx, request);
        case RequestCode.UPDATE_NAMESRV_CONFIG:
            return this.updateConfig(ctx, request);
        case RequestCode.GET_NAMESRV_CONFIG:
            return this.getConfig(ctx, request);
        default:
            break;
    }
    return null;
}

可以看到方法中判断的请求类型有很多,但我们主要重点关注如何处理Broker注册请求。而且其中还需要分开不同的版本,因为本次部署的RocketMQ是4.9版本,也是RocketMQ的最新版,所以接着看registerBrokerWithFilterServer方法是如何处理注册请求的:

public RemotingCommand registerBrokerWithFilterServer(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
    final RemotingCommand response = RemotingCommand.createResponseCommand(RegisterBrokerResponseHeader.class); // 响应体
    final RegisterBrokerResponseHeader responseHeader = (RegisterBrokerResponseHeader) response.readCustomHeader(); // 响应头
    final RegisterBrokerRequestHeader requestHeader = (RegisterBrokerRequestHeader) request.decodeCommandCustomHeader(RegisterBrokerRequestHeader.class); // 请求头,用于解析请求数据

    if (!checksum(ctx, request, requestHeader)) {
        response.setCode(ResponseCode.SYSTEM_ERROR);
        response.setRemark("crc32 not match");
        return response;
    }

    RegisterBrokerBody registerBrokerBody = new RegisterBrokerBody(); // Broker注册信息,用于解析请求体

    if (request.getBody() != null) {
        try {
            registerBrokerBody = RegisterBrokerBody.decode(request.getBody(), requestHeader.isCompressed()); // 解密注册请求体
        } catch (Exception e) {
            throw new RemotingCommandException("Failed to decode RegisterBrokerBody", e);
        }
    } else {
        registerBrokerBody.getTopicConfigSerializeWrapper().getDataVersion().setCounter(new AtomicLong(0));
        registerBrokerBody.getTopicConfigSerializeWrapper().getDataVersion().setTimestamp(0);
    }

    RegisterBrokerResult result = this.namesrvController.getRouteInfoManager().registerBroker(
        requestHeader.getClusterName(),
        requestHeader.getBrokerAddr(),
        requestHeader.getBrokerName(),
        requestHeader.getBrokerId(),
        requestHeader.getHaServerAddr(),
        registerBrokerBody.getTopicConfigSerializeWrapper(),
        registerBrokerBody.getFilterServerList(),
        ctx.channel()); // 重点方法,将Broker信息注册到路由管理器中,并返回注册结果

	// 封装注册结果到响应头和响应体
    responseHeader.setHaServerAddr(result.getHaServerAddr());
    responseHeader.setMasterAddr(result.getMasterAddr());

    byte[] jsonValue = this.namesrvController.getKvConfigManager().getKVListByNamespace(NamesrvUtil.NAMESPACE_ORDER_TOPIC_CONFIG);
    response.setBody(jsonValue);

    response.setCode(ResponseCode.SUCCESS);
    response.setRemark(null);
    return response;
}
  • 将Broker信息注册到NameServer的路由管理器中:
public RegisterBrokerResult registerBroker(
    final String clusterName,
    final String brokerAddr,
    final String brokerName,
    final long brokerId,
    final String haServerAddr,
    final TopicConfigSerializeWrapper topicConfigWrapper,
    final List<String> filterServerList,
    final Channel channel) {
    RegisterBrokerResult result = new RegisterBrokerResult();
    try {
        try {
            this.lock.writeLock().lockInterruptibly(); // 上写锁,保证写入信息线程安全
			
			/**
			* 更新clusterAddrTable
			*/
            Set<String> brokerNames = this.clusterAddrTable.get(clusterName);
            if (null == brokerNames) { 
                brokerNames = new HashSet<String>();
                this.clusterAddrTable.put(clusterName, brokerNames);
            }
            brokerNames.add(brokerName);

			/**
			* 更新brokerAddrTable
			*/
            boolean registerFirst = false; // 标识该Broker信息是不是首次注册,默认false
            BrokerData brokerData = this.brokerAddrTable.get(brokerName);
            if (null == brokerData) {
                registerFirst = true; // 该Broker是首次注册
                brokerData = new BrokerData(clusterName, brokerName, new HashMap<Long, String>());
                this.brokerAddrTable.put(brokerName, brokerData); // 直接添加,但是尚未包含Broker地址信息
            }
            // 在此需要做一次过滤,不同Broker之间,同一个Broker地址只能注册一次
            Map<Long, String> brokerAddrsMap = brokerData.getBrokerAddrs();
            Iterator<Entry<Long, String>> it = brokerAddrsMap.entrySet().iterator();
            while (it.hasNext()) { // 遍历指定brokerName下所有已注册的Broker地址信息
                Entry<Long, String> item = it.next();
                if (null != brokerAddr && brokerAddr.equals(item.getValue()) && brokerId != item.getKey()) { // Broker的id不同,即不同的Broker,已包含需要注册的Broker地址,即重复注册同一个Broker地址
                    it.remove(); // 移除这个Broker
                }
            }
            String oldAddr = brokerData.getBrokerAddrs().put(brokerId, brokerAddr); // 添加新的Broker地址信息,并返回旧Broker地址值
            registerFirst = registerFirst || (null == oldAddr); // 已经标识为首次注册,或者旧Broker地址值为空,代表该Broker首次注册

			/**
			* 更新topicQueueTable
			*/
            if (null != topicConfigWrapper && MixAll.MASTER_ID == brokerId) { // 注册的Broker属于主结点
                if (this.isBrokerTopicConfigChanged(brokerAddr, topicConfigWrapper.getDataVersion()) || registerFirst) { // Broker原有的地址信息有改动,或者有新的Broker信息加入
                    ConcurrentMap<String, TopicConfig> tcTable = topicConfigWrapper.getTopicConfigTable(); // 获取topic配置信息映射表 <topic名,topic队列相关信息>
                    if (tcTable != null) {
                        for (Map.Entry<String, TopicConfig> entry : tcTable.entrySet()) { // 遍历所有topic
                            this.createAndUpdateQueueData(brokerName, entry.getValue()); // 根据Broker的信息,为每个topic创建或者更新对应的队列信息
                        }
                    }
                }
            }

			/**
			* 更新brokerLiveTable
			*/
            BrokerLiveInfo prevBrokerLiveInfo = this.brokerLiveTable.put(brokerAddr,
                new BrokerLiveInfo(
                    System.currentTimeMillis(),
                    topicConfigWrapper.getDataVersion(),
                    channel,
                    haServerAddr)); // 直接添加对应的Broker状态信息,若有已存在相同的Broker(地址相同),则覆盖;否则,新增
            if (null == prevBrokerLiveInfo) {
                log.info("new broker registered, {} HAServer: {}", brokerAddr, haServerAddr);
            }

			/**
			* 更新filterServerTable
			*/
            if (filterServerList != null) {
                if (filterServerList.isEmpty()) {
                    this.filterServerTable.remove(brokerAddr);
                } else {
                    this.filterServerTable.put(brokerAddr, filterServerList);
                }
            }

            if (MixAll.MASTER_ID != brokerId) {
                String masterAddr = brokerData.getBrokerAddrs().get(MixAll.MASTER_ID); // 获取当前Broker的主结点
                // 将主结点信息封装到result结果对象中
                if (masterAddr != null) {
                    BrokerLiveInfo brokerLiveInfo = this.brokerLiveTable.get(masterAddr);
                    if (brokerLiveInfo != null) {
                        result.setHaServerAddr(brokerLiveInfo.getHaServerAddr());
                        result.setMasterAddr(masterAddr);
                    }
                }
            }
        } finally {
            this.lock.writeLock().unlock(); // 释放写锁
        }
    } catch (Exception e) {
        log.error("registerBroker Exception", e);
    }

    return result;
}
private void createAndUpdateQueueData(final String brokerName, final TopicConfig topicConfig) {
	// 创建消息队列对象
    QueueData queueData = new QueueData();
    queueData.setBrokerName(brokerName);
    queueData.setWriteQueueNums(topicConfig.getWriteQueueNums());
    queueData.setReadQueueNums(topicConfig.getReadQueueNums());
    queueData.setPerm(topicConfig.getPerm());
    queueData.setTopicSysFlag(topicConfig.getTopicSysFlag());

    List<QueueData> queueDataList = this.topicQueueTable.get(topicConfig.getTopicName()); // 根据topic名获取对应的队列列表
    if (null == queueDataList) { // 为空,说明不存在,则新增队列列表,并添加新队列
        queueDataList = new LinkedList<QueueData>();
        queueDataList.add(queueData);
        this.topicQueueTable.put(topicConfig.getTopicName(), queueDataList);
        log.info("new topic registered, {} {}", topicConfig.getTopicName(), queueData);
    } else { // 队列列表已存在,则更新队列
        boolean addNewOne = true; // 标志队列列表是否需要添加新队列,默认为true
        Iterator<QueueData> it = queueDataList.iterator();
        while (it.hasNext()) { // 遍历队列列表
            QueueData qd = it.next();
            if (qd.getBrokerName().equals(brokerName)) { // 存在同属一个Broker的队列
                if (qd.equals(queueData)) { // 队列其他信息都一致,说明此队列已存在,无需进行其他操作
                    addNewOne = false; // 标识为不需要添加新队列
                } else { // 否则,需要更新该队列
                    log.info("topic changed, {} OLD: {} NEW: {}", topicConfig.getTopicName(), qd, queueData);
                    it.remove();  // 先从列表中删除该队列
                }
            }
        }

        if (addNewOne) { // 判断需要添加新队列
            queueDataList.add(queueData); // 添加新队列
        }
    }
}

到此,Broker的核心源码解析结束。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值