更新broker配置AdminBrokerProcessor#processRequest#updateBrokerConfig
private synchronized RemotingCommand updateBrokerConfig(ChannelHandlerContext ctx, RemotingCommand request) {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
//根据channel远程地址更新broker的配置
log.info("updateBrokerConfig called by {}", RemotingHelper.parseChannelRemoteAddr(ctx.channel()));
byte[] body = request.getBody();
if (body != null) {
try {
String bodyStr = new String(body, MixAll.DEFAULT_CHARSET);
// 获取配置
Properties properties = MixAll.string2Properties(bodyStr);
if (properties != null) {
log.info("updateBrokerConfig, new config: [{}] client: {} ", properties, ctx.channel().remoteAddress());
// 更新持久存储配置
this.brokerController.getConfiguration().update(properties);
// 如果有权限设置强制更新
if (properties.containsKey("brokerPermission")) {
// 更新数据的版本号
this.brokerController.getTopicConfigManager().getDataVersion().nextVersion();
// 注册所有的broker
this.brokerController.registerBrokerAll(false, false, true);
}
} else {
log.error("string2Properties error");
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("string2Properties error");
return response;
}
} catch (UnsupportedEncodingException e) {
log.error("", e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("UnsupportedEncodingException " + e);
return response;
}
}
response.setCode(ResponseCode.SUCCESS);
response.setRemark(null);
return response;
}
Configuration#update
this.brokerController.getConfiguration().update(properties);
public void update(Properties properties) {
try {
// 读写锁同步实现
readWriteLock.writeLock().lockInterruptibly();
try {
// the property must be exist when update
//更新property配置 如果配置存在
mergeIfExist(properties, this.allConfigs);
for (Object configObject : configObjectList) {
// not allConfigs to update...
MixAll.properties2Object(properties, configObject);
}
// 更新数据的版本号
this.dataVersion.nextVersion();
} finally {
readWriteLock.writeLock().unlock();
}
} catch (InterruptedException e) {
log.error("update lock error, {}", properties);
return;
}
//持久化修改
persist();
}
Configuration#mergeIfExist
private void mergeIfExist(Properties from, Properties to) {
for (Object key : from.keySet()) {
if (!to.containsKey(key)) {
//原配置不存在直接下一个
continue;
}
Object fromObj = from.get(key), toObj = to.get(key);
//只是为了打印出谁替换了谁加的判断
if (toObj != null && !toObj.equals(fromObj)) {
log.info("Replace, key: {}, value: {} -> {}", key, toObj, fromObj);
}
to.put(key, fromObj);
}
}
Configuration#persist
public void persist() {
try {
readWriteLock.readLock().lockInterruptibly();
try {
String allConfigs = getAllConfigsInternal();
//获取getStorePath的路径的所有配置
MixAll.string2File(allConfigs, getStorePath());
} catch (IOException e) {
log.error("persist string2File error, ", e);
} finally {
readWriteLock.readLock().unlock();
}
} catch (InterruptedException e) {
log.error("persist lock error");
}
}
获取getStorePath的路径的所有配置getStorePath()
// 获取broker的配置文件路径
private String getStorePath() {
String realStorePath = null;
try {
readWriteLock.readLock().lockInterruptibly();
try {
// BrokerPathConfigHelper.getBrokerConfigPath()
realStorePath = this.storePath;
if (this.storePathFromConfig) {
try {
realStorePath = (String) storePathField.get(this.storePathObject);
} catch (IllegalAccessException e) {
log.error("getStorePath error, ", e);
}
}
} finally {
readWriteLock.readLock().unlock();
}
} catch (InterruptedException e) {
log.error("getStorePath lock error");
}
return realStorePath;
}
BrokerController#registerBrokerAll
AdminBrokerProcessor#updateBrokerConfig#this.brokerController.registerBrokerAll(false, false, true);
public synchronized void registerBrokerAll(final boolean checkOrderConfig, boolean oneway, boolean forceRegister) {
TopicConfigSerializeWrapper topicConfigWrapper = this.getTopicConfigManager().buildTopicConfigSerializeWrapper();
// 如果没有读写权限
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);
}
// 判断broker集群是否需要注册
if (forceRegister || needRegister(this.brokerConfig.getBrokerClusterName(),
this.getBrokerAddr(),
this.brokerConfig.getBrokerName(),
this.brokerConfig.getBrokerId(),
this.brokerConfig.getRegisterBrokerTimeoutMills())) {
// 向所有的broker注册topic配置信息
doRegisterBrokerAll(checkOrderConfig, oneway, topicConfigWrapper);
}
}
BrokerController#needRegister
private boolean needRegister(final String clusterName,
final String brokerAddr,
final String brokerName,
final long brokerId,
final int timeoutMills) {
TopicConfigSerializeWrapper topicConfigWrapper = this.getTopicConfigManager().buildTopicConfigSerializeWrapper();
// 获取所有的namesrv去请求判断是否发生变更
List<Boolean> changeList = brokerOuterAPI.needRegister(clusterName, brokerAddr, brokerName, brokerId, topicConfigWrapper, timeoutMills);
boolean needRegister = false;
for (Boolean changed : changeList) {
if (changed) {
//任意一个namesrv变更 都需要重新注册
needRegister = true;
break;
}
}
return needRegister;
}
BrokerOuterAPI#needRegister
brokerOuterAPI.needRegister
public List<Boolean> needRegister(
final String clusterName,
final String brokerAddr,
final String brokerName,
final long brokerId,
final TopicConfigSerializeWrapper topicConfigWrapper,
final int timeoutMills) {
final List<Boolean> changedList = new CopyOnWriteArrayList<>();
List<String> nameServerAddressList = this.remotingClient.getNameServerAddressList();
if (nameServerAddressList != null && nameServerAddressList.size() > 0) {
final CountDownLatch countDownLatch = new CountDownLatch(nameServerAddressList.size());
for (final String namesrvAddr : nameServerAddressList) {
brokerOuterExecutor.execute(new Runnable() {
@Override
public void run() {
try {
QueryDataVersionRequestHeader requestHeader = new QueryDataVersionRequestHeader();
requestHeader.setBrokerAddr(brokerAddr);
requestHeader.setBrokerId(brokerId);
requestHeader.setBrokerName(brokerName);
requestHeader.setClusterName(clusterName);
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.QUERY_DATA_VERSION, requestHeader);
request.setBody(topicConfigWrapper.getDataVersion().encode());
RemotingCommand response = remotingClient.invokeSync(namesrvAddr, request, timeoutMills);
DataVersion nameServerDataVersion = null;
Boolean changed = false;
switch (response.getCode()) {
case ResponseCode.SUCCESS: {
QueryDataVersionResponseHeader queryDataVersionResponseHeader =
(QueryDataVersionResponseHeader) response.decodeCommandCustomHeader(QueryDataVersionResponseHeader.class);
changed = queryDataVersionResponseHeader.getChanged();
byte[] body = response.getBody();
if (body != null) {
nameServerDataVersion = DataVersion.decode(body, DataVersion.class);
if (!topicConfigWrapper.getDataVersion().equals(nameServerDataVersion)) {
changed = true;
}
}
if (changed == null || changed) {
changedList.add(Boolean.TRUE);
}
}
default:
break;
}
log.warn("Query data version from name server {} OK,changed {}, broker {},name server {}", namesrvAddr, changed, topicConfigWrapper.getDataVersion(), nameServerDataVersion == null ? "" : nameServerDataVersion);
} catch (Exception e) {
changedList.add(Boolean.TRUE);
log.error("Query data version from name server {} Exception, {}", namesrvAddr, e);
} finally {
countDownLatch.countDown();
}
}
});
}
try {
countDownLatch.await(timeoutMills, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
log.error("query dataversion from nameserver countDownLatch await Exception", e);
}
}
return changedList;
}