/**
* Copyright (C) 2010-2013 Alibaba Group Holding Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.rocketmq.broker.slave;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.rocketmq.broker.BrokerController;
import com.alibaba.rocketmq.broker.subscription.SubscriptionGroupManager;
import com.alibaba.rocketmq.common.MixAll;
import com.alibaba.rocketmq.common.constant.LoggerName;
import com.alibaba.rocketmq.common.protocol.body.ConsumerOffsetSerializeWrapper;
import com.alibaba.rocketmq.common.protocol.body.SubscriptionGroupWrapper;
import com.alibaba.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
/**
* Slave从Master同步信息(非消息)
*
* chen.si 包括4类信息: 消费进度、定时进度、topic配置 和 sub group信息
*
* @author shijia.wxr<vintage.wang@gmail.com>
* @author manhong.yqd<manhong.yqd@taobao.com>
* @since 2013-7-8
*/
public class SlaveSynchronize {
private static final Logger log = LoggerFactory.getLogger(LoggerName.BrokerLoggerName);
private final BrokerController brokerController;
/**
* chen.si master的地址,slave通过这个地址对应的master中 拉取 相关元数据和进度信息
*/
private volatile String masterAddr = null;
public SlaveSynchronize(BrokerController brokerController) {
this.brokerController = brokerController;
}
public String getMasterAddr() {
return masterAddr;
}
public void setMasterAddr(String masterAddr) {
this.masterAddr = masterAddr;
}
public void syncAll() {
/**
* chen.si 同步其他的进度信息
*
* 物理消息 通过HaService同步;其他的信息,通过这里同步
*/
this.syncTopicConfig();
this.syncConsumerOffset();
this.syncDelayOffset();
this.syncSubscriptionGroupConfig();
}
private void syncTopicConfig() {
String masterAddrBak = this.masterAddr;
if (masterAddrBak != null) {
try {
/**
* chen.si 拉取topic信息
*/
TopicConfigSerializeWrapper topicWrapper =
this.brokerController.getBrokerOuterAPI().getAllTopicConfig(masterAddrBak);
/**
* chen.si 比较版本,因为topic一般的在线改动不大,所以增加个 版本,避免重复的同步
*/
if (!this.brokerController.getTopicConfigManager().getDataVersion()
.equals(topicWrapper.getDataVersion())) {
/**
* chen.si 更新topic信息
*/
this.brokerController.getTopicConfigManager().getDataVersion()
.assignNewOne(topicWrapper.getDataVersion());
this.brokerController.getTopicConfigManager().getTopicConfigTable().clear();
this.brokerController.getTopicConfigManager().getTopicConfigTable()
.putAll(topicWrapper.getTopicConfigTable());
/**
* chen.si 持久化到文件
*/
this.brokerController.getTopicConfigManager().persist();
log.info("update slave topic config from master, {}", masterAddrBak);
}
}
catch (Exception e) {
log.error("syncTopicConfig Exception, " + masterAddrBak, e);
}
}
}
private void syncConsumerOffset() {
String masterAddrBak = this.masterAddr;
if (masterAddrBak != null) {
try {
/**
* chen.si 拉取消费进度信息
*/
ConsumerOffsetSerializeWrapper offsetWrapper =
this.brokerController.getBrokerOuterAPI().getAllConsumerOffset(masterAddrBak);
/**
* chen.si 更新消费进度信息
*/
this.brokerController.getConsumerOffsetManager().getOffsetTable()
.putAll(offsetWrapper.getOffsetTable());
/**
* chen.si 持久化到文件
*/
this.brokerController.getConsumerOffsetManager().persist();
log.info("update slave consumer offset from master, {}", masterAddrBak);
}
catch (Exception e) {
log.error("syncConsumerOffset Exception, " + masterAddrBak, e);
}
}
}
private void syncDelayOffset() {
String masterAddrBak = this.masterAddr;
if (masterAddrBak != null) {
try {
/**
* chen.si 拉取定时消息处理进度信息
*/
String delayOffset =
this.brokerController.getBrokerOuterAPI().getAllDelayOffset(masterAddrBak);
if (delayOffset != null) {
/**
* chen.si 持久化到文件
*/
String fileName = this.brokerController.getMessageStoreConfig().getDelayOffsetStorePath();
try {
MixAll.string2File(delayOffset, fileName);
}
catch (IOException e) {
log.error("persist file Exception, " + fileName, e);
}
}
log.info("update slave delay offset from master, {}", masterAddrBak);
}
catch (Exception e) {
log.error("syncDelayOffset Exception, " + masterAddrBak, e);
}
}
}
private void syncSubscriptionGroupConfig() {
String masterAddrBak = this.masterAddr;
if (masterAddrBak != null) {
try {
/**
* chen.si TODO 拉取 SubscriptionGroup 信息
*/
SubscriptionGroupWrapper subscriptionWrapper =
this.brokerController.getBrokerOuterAPI()
.getAllSubscriptionGroupConfig(masterAddrBak);
/**
* chen.si 比较版本
*/
if (!this.brokerController.getSubscriptionGroupManager().getDataVersion()
.equals(subscriptionWrapper.getDataVersion())) {
/**
* chen.si 更新信息
*/
SubscriptionGroupManager subscriptionGroupManager =
this.brokerController.getSubscriptionGroupManager();
subscriptionGroupManager.getDataVersion().assignNewOne(
subscriptionWrapper.getDataVersion());
subscriptionGroupManager.getSubscriptionGroupTable().clear();
subscriptionGroupManager.getSubscriptionGroupTable().putAll(
subscriptionWrapper.getSubscriptionGroupTable());
/**
* chen.si 更新到文件
*/
subscriptionGroupManager.persist();
log.info("update slave Subscription Group from master, {}", masterAddrBak);
}
}
catch (Exception e) {
log.error("syncSubscriptionGroup Exception, " + masterAddrBak, e);
}
}
}
}