根据前面介绍,可以看到broker在启动的时候要向namesrv注册自己,这里我们就来看看broker怎么向namesrv注册自己。
在BrokerController的start()中会向注册namesrv注册自己,并启动定时注册Broker到Name Server的任务。
- start()方法中的注册方法:
// 启动时,强制注册
this.registerBrokerAll(true, false);
// 定时注册Broker到Name Server
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
try {
BrokerController.this.registerBrokerAll(true, false);
} catch (Throwable e) {
log.error("registerBrokerAll Exception", e);
}
}
}, 1000 * 10, 1000 * 30, TimeUnit.MILLISECONDS);
- 接着看registerBrokerAll方法:
/** * 定时注册Broker到Name Server * @param checkOrderConfig * @param oneway */ public synchronized void registerBrokerAll(final boolean checkOrderConfig, boolean oneway) { TopicConfigSerializeWrapper topicConfigWrapper = this.getTopicConfigManager().buildTopicConfigSerializeWrapper(); //每次注册的时候都会 同步Broker最新的读写权限到每一个topic中(TopicConfig对象中),放到TopicConfigTable中 //注册的时候要携带这些信息 if (!PermName.isWriteable(this.getBrokerConfig().getBrokerPermission()) || !PermName.isReadable(this.getBrokerConfig().getBrokerPermission())) { ConcurrentHashMap<String, TopicConfig> topicConfigTable = new ConcurrentHashMap<String, TopicConfig>(); for (TopicConfig topicConfig : topicConfigWrapper.getTopicConfigTable().values()) { TopicConfig tmp = new TopicConfig(topicConfig.getTopicName(), topicConfig.getReadQueueNums(), topicConfig.getWriteQueueNums(), this.brokerConfig.getBrokerPermission()); topicConfigTable.put(topicConfig.getTopicName(), tmp); } topicConfigWrapper.setTopicConfigTable(topicConfigTable); } /** * 注册时携带的信息是: * cluster name,broker 地址,broker name,broker id //0为master 1为slave,HA地址,即slave可以通过该地址与master进行数据同步 * topic信息 包含topic name,read queue num, write queue num, permission */ 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()); if (registerBrokerResult != null) { if (this.updateMasterHAServerAddrPeriodically && registerBrokerResult.getHaServerAddr() != null) { this.messageStore.updateHaMasterAddress(registerBrokerResult.getHaServerAddr()); } this.slaveSynchronize.setMasterAddr(registerBrokerResult.getMasterAddr()); // 检查 topic config 的顺序消息配置 if (checkOrderConfig) { this.getTopicConfigManager().updateOrderTopicConfig(registerBrokerResult.getKvTable()); } } }
- 接着看BrokerOuterAPI类的registerBrokerAll方法
/** * 注册Broker到Name Server * @param clusterName * @param brokerAddr * @param brokerName * @param brokerId * @param haServerAddr * @param topicConfigWrapper * @param filterServerList * @param oneway * @param timeoutMills * @return */ public RegisterBrokerResult registerBrokerAll(// final String clusterName, // 1 final String brokerAddr, // 2 final String brokerName, // 3 final long brokerId, // 4 final String haServerAddr, // 5 final TopicConfigSerializeWrapper topicConfigWrapper, // 6 final List<String> filterServerList, // 7 final boolean oneway,// 8 final int timeoutMills// 9 ) { RegisterBrokerResult registerBrokerResult = null; //获取namesrv的地址信息列表 List<String> nameServerAddressList = this.remotingClient.getNameServerAddressList(); if (nameServerAddressList != null) { for (String namesrvAddr : nameServerAddressList) { //循环namesrv的信息列表把broker注册到每一个namesrv中 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 e) { log.warn("registerBroker Exception, " + namesrvAddr, e); } } } return registerBrokerResult; }
- 接着看BrokerOuterAPI类的registerBroker方法
private RegisterBrokerResult registerBroker(// final String namesrvAddr, // final String clusterName, // 1 final String brokerAddr, // 2 final String brokerName, // 3 final long brokerId, // 4 final String haServerAddr, // 5 final TopicConfigSerializeWrapper topicConfigWrapper, // 6 final List<String> filterServerList, // 7 final boolean oneway,// 8 final int timeoutMills// 9 ) 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); //这里利用命令模式对请求的信息进行封装,告诉接收请求的service端,该请求的目的是什么(比如这里的REGISTER_BROKER,告诉service端该请求是注册broker) RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.REGISTER_BROKER, requestHeader); RegisterBrokerBody requestBody = new RegisterBrokerBody(); requestBody.setTopicConfigSerializeWrapper(topicConfigWrapper); requestBody.setFilterServerList(filterServerList); request.setBody(requestBody.encode()); //以上就完成了向namesrv注册broker的请求头和请求体 if (oneway) { try { this.remotingClient.invokeOneway(namesrvAddr, request, timeoutMills); } catch (RemotingTooMuchRequestException e) { } return null; } RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, timeoutMills); assert response != null; switch (response.getCode()) { case ResponseCode.SUCCESS: { RegisterBrokerResponseHeader responseHeader = (RegisterBrokerResponseHeader) response.decodeCommandCustomHeader(RegisterBrokerResponseHeader.class); RegisterBrokerResult result = new RegisterBrokerResult(); result.setMasterAddr(responseHeader.getMasterAddr()); result.setHaServerAddr(responseHeader.getHaServerAddr()); 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()); }
RemotingCommand response = this.remotingClient.invokeSync(namesrvAddr, request, timeoutMills);
调用invokeSync方法进行broker的注册。通信后面专门看看
大体的说明都在写在了方法的注释上面了。