This commit is contained in:
agapple
2014-09-23 15:11:35 +08:00
commit a0defe575b
331 changed files with 53031 additions and 0 deletions

20
instance/manager/pom.xml Normal file
View File

@@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal</artifactId>
<version>1.0.19-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.instance.manager</artifactId>
<packaging>jar</packaging>
<name>canal instance manager module for otter ${project.version}</name>
<dependencies>
<dependency>
<groupId>com.alibaba.otter</groupId>
<artifactId>canal.instance.core</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,29 @@
package com.alibaba.otter.canal.instance.manager;
import com.alibaba.otter.canal.instance.manager.model.Canal;
/**
* 对应canal的配置
*
* @author jianghang 2012-7-4 下午03:09:17
* @version 1.0.0
*/
public class CanalConfigClient {
/**
* 根据对应的destinantion查询Canal信息
*/
public Canal findCanal(String destination) {
// TODO 根据自己的业务实现
throw new UnsupportedOperationException();
}
/**
* 根据对应的destinantion查询filter信息
*/
public String findFilter(String destination) {
// TODO 根据自己的业务实现
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,550 @@
package com.alibaba.otter.canal.instance.manager;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;
import com.alibaba.otter.canal.common.CanalException;
import com.alibaba.otter.canal.common.alarm.CanalAlarmHandler;
import com.alibaba.otter.canal.common.alarm.LogAlarmHandler;
import com.alibaba.otter.canal.common.utils.JsonUtils;
import com.alibaba.otter.canal.common.zookeeper.ZkClientx;
import com.alibaba.otter.canal.filter.aviater.AviaterRegexFilter;
import com.alibaba.otter.canal.instance.core.CanalInstance;
import com.alibaba.otter.canal.instance.core.CanalInstanceSupport;
import com.alibaba.otter.canal.instance.manager.model.Canal;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.DataSourcing;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.HAMode;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.IndexMode;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.MetaMode;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.SourcingType;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.StorageMode;
import com.alibaba.otter.canal.instance.manager.model.CanalParameter.StorageScavengeMode;
import com.alibaba.otter.canal.meta.CanalMetaManager;
import com.alibaba.otter.canal.meta.MemoryMetaManager;
import com.alibaba.otter.canal.meta.PeriodMixedMetaManager;
import com.alibaba.otter.canal.meta.ZooKeeperMetaManager;
import com.alibaba.otter.canal.parse.CanalEventParser;
import com.alibaba.otter.canal.parse.ha.CanalHAController;
import com.alibaba.otter.canal.parse.ha.HeartBeatHAController;
import com.alibaba.otter.canal.parse.inbound.AbstractEventParser;
import com.alibaba.otter.canal.parse.inbound.group.GroupEventParser;
import com.alibaba.otter.canal.parse.inbound.mysql.LocalBinlogEventParser;
import com.alibaba.otter.canal.parse.inbound.mysql.MysqlEventParser;
import com.alibaba.otter.canal.parse.index.CanalLogPositionManager;
import com.alibaba.otter.canal.parse.index.FailbackLogPositionManager;
import com.alibaba.otter.canal.parse.index.MemoryLogPositionManager;
import com.alibaba.otter.canal.parse.index.MetaLogPositionManager;
import com.alibaba.otter.canal.parse.index.PeriodMixedLogPositionManager;
import com.alibaba.otter.canal.parse.index.ZooKeeperLogPositionManager;
import com.alibaba.otter.canal.parse.support.AuthenticationInfo;
import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
import com.alibaba.otter.canal.protocol.ClientIdentity;
import com.alibaba.otter.canal.protocol.position.EntryPosition;
import com.alibaba.otter.canal.sink.CanalEventSink;
import com.alibaba.otter.canal.sink.entry.EntryEventSink;
import com.alibaba.otter.canal.sink.entry.group.GroupEventSink;
import com.alibaba.otter.canal.store.AbstractCanalStoreScavenge;
import com.alibaba.otter.canal.store.CanalEventStore;
import com.alibaba.otter.canal.store.memory.MemoryEventStoreWithBuffer;
import com.alibaba.otter.canal.store.model.BatchMode;
import com.alibaba.otter.canal.store.model.Event;
/**
* 单个canal实例,比如一个destination会独立一个实例
*
* @author jianghang 2012-7-11 下午09:26:51
* @version 1.0.0
*/
public class CanalInstanceWithManager extends CanalInstanceSupport implements CanalInstance {
private static final Logger logger = LoggerFactory.getLogger(CanalInstanceWithManager.class);
protected Long canalId; // 和manager交互唯一标示
protected String destination; // 队列名字
protected String filter; // 过滤表达式
protected CanalParameter parameters; // 对应参数
protected CanalMetaManager metaManager; // 消费信息管理器
protected CanalEventStore<Event> eventStore; // 有序队列
protected CanalEventParser eventParser; // 解析对应的数据信息
protected CanalEventSink<List<Entry>> eventSink; // 链接parse和store的桥接器
protected CanalAlarmHandler alarmHandler; // alarm报警机制
protected ZkClientx zkClientx;
public CanalInstanceWithManager(Canal canal){
this(canal, null);
}
public CanalInstanceWithManager(Canal canal, String filter){
this.parameters = canal.getCanalParameter();
this.canalId = canal.getId();
this.destination = canal.getName();
this.filter = filter;
logger.info("init CannalInstance for {}-{} with parameters:{}",
new Object[] { canalId, destination, parameters });
// 初始化报警机制
initAlarmHandler();
// 初始化metaManager
initMetaManager();
// 初始化eventStore
initEventStore();
// 初始化eventSink
initEventSink();
// 初始化eventParser;
initEventParser();
// 基础工具,需要提前start,会有先订阅再根据filter条件启动paser的需求
if (!alarmHandler.isStart()) {
alarmHandler.start();
}
if (!metaManager.isStart()) {
metaManager.start();
}
logger.info("init successful....");
}
public void start() {
super.start();
// 初始化metaManager
logger.info("start CannalInstance for {}-{} with parameters:{}", new Object[] { canalId, destination,
parameters });
if (!metaManager.isStart()) {
metaManager.start();
}
if (!alarmHandler.isStart()) {
alarmHandler.start();
}
if (!eventStore.isStart()) {
eventStore.start();
}
if (!eventSink.isStart()) {
eventSink.start();
}
if (!eventParser.isStart()) {
beforeStartEventParser(eventParser);
eventParser.start();
}
logger.info("start successful....");
}
public void stop() {
logger.info("stop CannalInstance for {}-{} ", new Object[] { canalId, destination });
if (eventParser.isStart()) {
eventParser.stop();
afterStopEventParser(eventParser);
}
if (eventSink.isStart()) {
eventSink.stop();
}
if (eventStore.isStart()) {
eventStore.stop();
}
if (metaManager.isStart()) {
metaManager.stop();
}
if (alarmHandler.isStart()) {
alarmHandler.stop();
}
// if (zkClientx != null) {
// zkClientx.close();
// }
super.stop();
logger.info("stop successful....");
}
public boolean subscribeChange(ClientIdentity identity) {
if (StringUtils.isNotEmpty(identity.getFilter())) {
AviaterRegexFilter aviaterFilter = new AviaterRegexFilter(identity.getFilter());
boolean isGroup = (eventParser instanceof GroupEventParser);
if (isGroup) {
// 处理group的模式
List<CanalEventParser> eventParsers = ((GroupEventParser) eventParser).getEventParsers();
for (CanalEventParser singleEventParser : eventParsers) {// 需要遍历启动
((AbstractEventParser) singleEventParser).setEventFilter(aviaterFilter);
}
} else {
((AbstractEventParser) eventParser).setEventFilter(aviaterFilter);
}
}
// filter的处理规则
// a. parser处理数据过滤处理
// b. sink处理数据的路由&分发,一份parse数据经过sink后可以分发为多份,每份的数据可以根据自己的过滤规则不同而有不同的数据
// 后续内存版的一对多分发,可以考虑
return true;
}
protected void afterStartEventParser(CanalEventParser eventParser) {
super.afterStartEventParser(eventParser);
// 读取一下历史订阅的filter信息
List<ClientIdentity> clientIdentitys = metaManager.listAllSubscribeInfo(destination);
for (ClientIdentity clientIdentity : clientIdentitys) {
subscribeChange(clientIdentity);
}
}
protected void initAlarmHandler() {
logger.info("init alarmHandler begin...");
alarmHandler = new LogAlarmHandler();
logger.info("init alarmHandler end! \n\t load CanalAlarmHandler:{} ", alarmHandler.getClass().getName());
}
protected void initMetaManager() {
logger.info("init metaManager begin...");
MetaMode mode = parameters.getMetaMode();
if (mode.isMemory()) {
metaManager = new MemoryMetaManager();
} else if (mode.isZookeeper()) {
metaManager = new ZooKeeperMetaManager();
((ZooKeeperMetaManager) metaManager).setZkClientx(getZkclientx());
} else if (mode.isMixed()) {
// metaManager = new MixedMetaManager();
metaManager = new PeriodMixedMetaManager();// 换用优化过的mixed, at
// 2012-09-11
// 设置内嵌的zk metaManager
ZooKeeperMetaManager zooKeeperMetaManager = new ZooKeeperMetaManager();
zooKeeperMetaManager.setZkClientx(getZkclientx());
((PeriodMixedMetaManager) metaManager).setZooKeeperMetaManager(zooKeeperMetaManager);
} else {
throw new CanalException("unsupport MetaMode for " + mode);
}
logger.info("init metaManager end! \n\t load CanalMetaManager:{} ", metaManager.getClass().getName());
}
protected void initEventStore() {
logger.info("init eventStore begin...");
StorageMode mode = parameters.getStorageMode();
if (mode.isMemory()) {
MemoryEventStoreWithBuffer memoryEventStore = new MemoryEventStoreWithBuffer();
memoryEventStore.setBufferSize(parameters.getMemoryStorageBufferSize());
memoryEventStore.setBufferMemUnit(parameters.getMemoryStorageBufferMemUnit());
memoryEventStore.setBatchMode(BatchMode.valueOf(parameters.getStorageBatchMode().name()));
memoryEventStore.setDdlIsolation(parameters.getDdlIsolation());
eventStore = memoryEventStore;
} else if (mode.isFile()) {
// 后续版本支持
throw new CanalException("unsupport MetaMode for " + mode);
} else if (mode.isMixed()) {
// 后续版本支持
throw new CanalException("unsupport MetaMode for " + mode);
} else {
throw new CanalException("unsupport MetaMode for " + mode);
}
if (eventStore instanceof AbstractCanalStoreScavenge) {
StorageScavengeMode scavengeMode = parameters.getStorageScavengeMode();
AbstractCanalStoreScavenge eventScavengeStore = (AbstractCanalStoreScavenge) eventStore;
eventScavengeStore.setDestination(destination);
eventScavengeStore.setCanalMetaManager(metaManager);
eventScavengeStore.setOnAck(scavengeMode.isOnAck());
eventScavengeStore.setOnFull(scavengeMode.isOnFull());
eventScavengeStore.setOnSchedule(scavengeMode.isOnSchedule());
if (scavengeMode.isOnSchedule()) {
eventScavengeStore.setScavengeSchedule(parameters.getScavengeSchdule());
}
}
logger.info("init eventStore end! \n\t load CanalEventStore:{}", eventStore.getClass().getName());
}
protected void initEventSink() {
logger.info("init eventSink begin...");
int groupSize = getGroupSize();
if (groupSize <= 1) {
eventSink = new EntryEventSink();
} else {
eventSink = new GroupEventSink(groupSize);
}
if (eventSink instanceof EntryEventSink) {
((EntryEventSink) eventSink).setFilterTransactionEntry(false);
((EntryEventSink) eventSink).setEventStore(getEventStore());
}
// if (StringUtils.isNotEmpty(filter)) {
// AviaterRegexFilter aviaterFilter = new AviaterRegexFilter(filter);
// ((AbstractCanalEventSink) eventSink).setFilter(aviaterFilter);
// }
logger.info("init eventSink end! \n\t load CanalEventSink:{}", eventSink.getClass().getName());
}
protected void initEventParser() {
logger.info("init eventParser begin...");
SourcingType type = parameters.getSourcingType();
List<List<DataSourcing>> groupDbAddresses = parameters.getGroupDbAddresses();
if (!CollectionUtils.isEmpty(groupDbAddresses)) {
int size = groupDbAddresses.get(0).size();// 取第一个分组的数量,主备分组的数量必须一致
List<CanalEventParser> eventParsers = new ArrayList<CanalEventParser>();
for (int i = 0; i < size; i++) {
List<InetSocketAddress> dbAddress = new ArrayList<InetSocketAddress>();
SourcingType lastType = null;
for (List<DataSourcing> groupDbAddress : groupDbAddresses) {
if (lastType != null && !lastType.equals(groupDbAddress.get(i).getType())) {
throw new CanalException(String.format("master/slave Sourcing type is unmatch. %s vs %s",
lastType,
groupDbAddress.get(i).getType()));
}
lastType = groupDbAddress.get(i).getType();
dbAddress.add(groupDbAddress.get(i).getDbAddress());
}
// 初始化其中的一个分组parser
eventParsers.add(doInitEventParser(lastType, dbAddress));
}
if (eventParsers.size() > 1) { // 如果存在分组,构造分组的parser
GroupEventParser groupEventParser = new GroupEventParser();
groupEventParser.setEventParsers(eventParsers);
this.eventParser = groupEventParser;
} else {
this.eventParser = eventParsers.get(0);
}
} else {
// 创建一个空数据库地址的parser,可能使用了tddl指定地址,启动的时候才会从tddl获取地址
this.eventParser = doInitEventParser(type, new ArrayList<InetSocketAddress>());
}
logger.info("init eventParser end! \n\t load CanalEventParser:{}", eventParser.getClass().getName());
}
private CanalEventParser doInitEventParser(SourcingType type, List<InetSocketAddress> dbAddresses) {
CanalEventParser eventParser = null;
if (type.isMysql()) {
MysqlEventParser mysqlEventParser = new MysqlEventParser();
mysqlEventParser.setDestination(destination);
// 编码参数
mysqlEventParser.setConnectionCharset(Charset.forName(parameters.getConnectionCharset()));
mysqlEventParser.setConnectionCharsetNumber(parameters.getConnectionCharsetNumber());
// 网络相关参数
mysqlEventParser.setDefaultConnectionTimeoutInSeconds(parameters.getDefaultConnectionTimeoutInSeconds());
mysqlEventParser.setSendBufferSize(parameters.getSendBufferSize());
mysqlEventParser.setReceiveBufferSize(parameters.getReceiveBufferSize());
// 心跳检查参数
mysqlEventParser.setDetectingEnable(parameters.getDetectingEnable());
mysqlEventParser.setDetectingSQL(parameters.getDetectingSQL());
mysqlEventParser.setDetectingIntervalInSeconds(parameters.getDetectingIntervalInSeconds());
// 数据库信息参数
mysqlEventParser.setSlaveId(parameters.getSlaveId());
if (!CollectionUtils.isEmpty(dbAddresses)) {
mysqlEventParser.setMasterInfo(new AuthenticationInfo(dbAddresses.get(0),
parameters.getDbUsername(),
parameters.getDbPassword(),
parameters.getDefaultDatabaseName()));
if (dbAddresses.size() > 1) {
mysqlEventParser.setStandbyInfo(new AuthenticationInfo(dbAddresses.get(1),
parameters.getDbUsername(),
parameters.getDbPassword(),
parameters.getDefaultDatabaseName()));
}
}
if (!CollectionUtils.isEmpty(parameters.getPositions())) {
EntryPosition masterPosition = JsonUtils.unmarshalFromString(parameters.getPositions().get(0),
EntryPosition.class);
// binlog位置参数
mysqlEventParser.setMasterPosition(masterPosition);
if (parameters.getPositions().size() > 1) {
EntryPosition standbyPosition = JsonUtils.unmarshalFromString(parameters.getPositions().get(0),
EntryPosition.class);
mysqlEventParser.setStandbyPosition(standbyPosition);
}
}
mysqlEventParser.setFallbackIntervalInSeconds(parameters.getFallbackIntervalInSeconds());
mysqlEventParser.setProfilingEnabled(false);
mysqlEventParser.setFilterTableError(parameters.getFilterTableError());
eventParser = mysqlEventParser;
} else if (type.isLocalBinlog()) {
LocalBinlogEventParser localBinlogEventParser = new LocalBinlogEventParser();
localBinlogEventParser.setDestination(destination);
localBinlogEventParser.setBufferSize(parameters.getReceiveBufferSize());
localBinlogEventParser.setConnectionCharset(Charset.forName(parameters.getConnectionCharset()));
localBinlogEventParser.setConnectionCharsetNumber(parameters.getConnectionCharsetNumber());
localBinlogEventParser.setDirectory(parameters.getLocalBinlogDirectory());
localBinlogEventParser.setProfilingEnabled(false);
localBinlogEventParser.setDetectingEnable(parameters.getDetectingEnable());
localBinlogEventParser.setDetectingIntervalInSeconds(parameters.getDetectingIntervalInSeconds());
localBinlogEventParser.setFilterTableError(parameters.getFilterTableError());
// 数据库信息,反查表结构时需要
if (!CollectionUtils.isEmpty(dbAddresses)) {
localBinlogEventParser.setMasterInfo(new AuthenticationInfo(dbAddresses.get(0),
parameters.getDbUsername(),
parameters.getDbPassword(),
parameters.getDefaultDatabaseName()));
}
eventParser = localBinlogEventParser;
} else if (type.isOracle()) {
throw new CanalException("unsupport SourcingType for " + type);
} else {
throw new CanalException("unsupport SourcingType for " + type);
}
// add transaction support at 2012-12-06
if (eventParser instanceof AbstractEventParser) {
AbstractEventParser abstractEventParser = (AbstractEventParser) eventParser;
abstractEventParser.setTransactionSize(parameters.getTransactionSize());
abstractEventParser.setLogPositionManager(initLogPositionManager());
abstractEventParser.setAlarmHandler(getAlarmHandler());
abstractEventParser.setEventSink(getEventSink());
if (StringUtils.isNotEmpty(filter)) {
AviaterRegexFilter aviaterFilter = new AviaterRegexFilter(filter);
abstractEventParser.setEventFilter(aviaterFilter);
}
// 设置黑名单
if (StringUtils.isNotEmpty(parameters.getBlackFilter())) {
AviaterRegexFilter aviaterFilter = new AviaterRegexFilter(parameters.getBlackFilter());
abstractEventParser.setEventBlackFilter(aviaterFilter);
}
}
if (eventParser instanceof MysqlEventParser) {
MysqlEventParser mysqlEventParser = (MysqlEventParser) eventParser;
// 初始化haController,绑定与eventParser的关系,haController会控制eventParser
CanalHAController haController = initHaController();
mysqlEventParser.setHaController(haController);
}
return eventParser;
}
protected CanalHAController initHaController() {
logger.info("init haController begin...");
HAMode haMode = parameters.getHaMode();
CanalHAController haController = null;
if (haMode.isHeartBeat()) {
haController = new HeartBeatHAController();
((HeartBeatHAController) haController).setDetectingRetryTimes(parameters.getDetectingRetryTimes());
((HeartBeatHAController) haController).setSwitchEnable(parameters.getHeartbeatHaEnable());
} else {
throw new CanalException("unsupport HAMode for " + haMode);
}
logger.info("init haController end! \n\t load CanalHAController:{}", haController.getClass().getName());
return haController;
}
protected CanalLogPositionManager initLogPositionManager() {
logger.info("init logPositionPersistManager begin...");
IndexMode indexMode = parameters.getIndexMode();
CanalLogPositionManager logPositionManager = null;
if (indexMode.isMemory()) {
logPositionManager = new MemoryLogPositionManager();
} else if (indexMode.isZookeeper()) {
logPositionManager = new ZooKeeperLogPositionManager();
((ZooKeeperLogPositionManager) logPositionManager).setZkClientx(getZkclientx());
} else if (indexMode.isMixed()) {
logPositionManager = new PeriodMixedLogPositionManager();
ZooKeeperLogPositionManager zooKeeperLogPositionManager = new ZooKeeperLogPositionManager();
zooKeeperLogPositionManager.setZkClientx(getZkclientx());
((PeriodMixedLogPositionManager) logPositionManager).setZooKeeperLogPositionManager(zooKeeperLogPositionManager);
} else if (indexMode.isMeta()) {
logPositionManager = new MetaLogPositionManager();
((MetaLogPositionManager) logPositionManager).setMetaManager(metaManager);
} else if (indexMode.isMemoryMetaFailback()) {
MemoryLogPositionManager primaryLogPositionManager = new MemoryLogPositionManager();
MetaLogPositionManager failbackLogPositionManager = new MetaLogPositionManager();
failbackLogPositionManager.setMetaManager(metaManager);
logPositionManager = new FailbackLogPositionManager();
((FailbackLogPositionManager) logPositionManager).setPrimary(primaryLogPositionManager);
((FailbackLogPositionManager) logPositionManager).setFailback(failbackLogPositionManager);
} else {
throw new CanalException("unsupport indexMode for " + indexMode);
}
logger.info("init logPositionManager end! \n\t load CanalLogPositionManager:{}", logPositionManager.getClass()
.getName());
return logPositionManager;
}
protected void startEventParserInternal(CanalEventParser eventParser, boolean isGroup) {
if (eventParser instanceof AbstractEventParser) {
AbstractEventParser abstractEventParser = (AbstractEventParser) eventParser;
abstractEventParser.setAlarmHandler(getAlarmHandler());
}
super.startEventParserInternal(eventParser, isGroup);
}
private int getGroupSize() {
List<List<DataSourcing>> groupDbAddresses = parameters.getGroupDbAddresses();
if (!CollectionUtils.isEmpty(groupDbAddresses)) {
return groupDbAddresses.get(0).size();
} else {
// 可能是基于tddl的启动
return 1;
}
}
private synchronized ZkClientx getZkclientx() {
// 做一下排序,保证相同的机器只使用同一个链接
List<String> zkClusters = new ArrayList<String>(parameters.getZkClusters());
Collections.sort(zkClusters);
return ZkClientx.getZkClient(StringUtils.join(zkClusters, ";"));
}
// =====================================
public String getDestination() {
return destination;
}
public CanalMetaManager getMetaManager() {
return metaManager;
}
public CanalEventStore<Event> getEventStore() {
return eventStore;
}
public CanalEventParser getEventParser() {
return eventParser;
}
public CanalEventSink<List<Entry>> getEventSink() {
return eventSink;
}
public CanalAlarmHandler getAlarmHandler() {
return alarmHandler;
}
public void setAlarmHandler(CanalAlarmHandler alarmHandler) {
this.alarmHandler = alarmHandler;
}
}

View File

@@ -0,0 +1,29 @@
package com.alibaba.otter.canal.instance.manager;
import com.alibaba.otter.canal.instance.core.CanalInstance;
import com.alibaba.otter.canal.instance.core.CanalInstanceGenerator;
import com.alibaba.otter.canal.instance.manager.model.Canal;
/**
* 基于manager生成对应的{@linkplain CanalInstance}
*
* @author jianghang 2012-7-12 下午05:37:09
* @version 1.0.0
*/
public class ManagerCanalInstanceGenerator implements CanalInstanceGenerator {
private CanalConfigClient canalConfigClient;
public CanalInstance generate(String destination) {
Canal canal = canalConfigClient.findCanal(destination);
String filter = canalConfigClient.findFilter(destination);
return new CanalInstanceWithManager(canal, filter);
}
// ================ setter / getter ================
public void setCanalConfigClient(CanalConfigClient canalConfigClient) {
this.canalConfigClient = canalConfigClient;
}
}

View File

@@ -0,0 +1,88 @@
package com.alibaba.otter.canal.instance.manager.model;
import java.io.Serializable;
import java.util.Date;
import org.apache.commons.lang.builder.ToStringBuilder;
import com.alibaba.otter.canal.common.utils.CanalToStringStyle;
/**
* 对应的canal模型对象
*
* @author jianghang 2012-7-4 下午02:32:39
* @version 1.0.0
*/
public class Canal implements Serializable {
private static final long serialVersionUID = 8333284022624682754L;
private Long id;
private String name; // 对应的名字
private String desc; // 描述
private CanalStatus status;
private CanalParameter canalParameter; // 参数定义
private Date gmtCreate; // 创建时间
private Date gmtModified; // 修改时间
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public CanalParameter getCanalParameter() {
return canalParameter;
}
public void setCanalParameter(CanalParameter canalParameter) {
this.canalParameter = canalParameter;
}
public CanalStatus getStatus() {
return status;
}
public void setStatus(CanalStatus status) {
this.status = status;
}
public Date getGmtCreate() {
return gmtCreate;
}
public void setGmtCreate(Date gmtCreate) {
this.gmtCreate = gmtCreate;
}
public Date getGmtModified() {
return gmtModified;
}
public void setGmtModified(Date gmtModified) {
this.gmtModified = gmtModified;
}
public String toString() {
return ToStringBuilder.reflectionToString(this, CanalToStringStyle.DEFAULT_STYLE);
}
}

View File

@@ -0,0 +1,865 @@
package com.alibaba.otter.canal.instance.manager.model;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.ToStringBuilder;
import com.alibaba.otter.canal.common.utils.CanalToStringStyle;
/**
* canal运行相关参数
*
* @author jianghang 2012-7-4 下午02:52:52
* @version 1.0.0
*/
public class CanalParameter implements Serializable {
private static final long serialVersionUID = -5893459662315430900L;
private Long canalId;
// 相关参数
private RunMode runMode = RunMode.EMBEDDED; // 运行模式:嵌入式/服务式
private ClusterMode clusterMode = ClusterMode.STANDALONE; // 集群模式:单机/冷备/热备份
private Long zkClusterId; // zk集群id,为管理方便
private List<String> zkClusters; // zk集群地址
// meta相关参数
private MetaMode metaMode = MetaMode.MEMORY; // meta机制
// storage存储
private Integer transactionSize = 1024; // 支持处理的transaction事务大小
private StorageMode storageMode = StorageMode.MEMORY; // 存储机制
private BatchMode storageBatchMode = BatchMode.MEMSIZE; // 基于大小返回结果
private Integer memoryStorageBufferSize = 16 * 1024; // 内存存储的buffer大小
private Integer memoryStorageBufferMemUnit = 1024; // 内存存储的buffer内存占用单位,默认为1kb
private String fileStorageDirectory; // 文件存储的目录位置
private Integer fileStorageStoreCount; // 每个文件store存储的记录数
private Integer fileStorageRollverCount; // store文件的个数
private Integer fileStoragePercentThresold; // 整个store存储占disk硬盘的百分比,超过百分比及时条数还未满也不写入
private StorageScavengeMode storageScavengeMode = StorageScavengeMode.ON_ACK;
private String scavengeSchdule; // 调度规则
// replcation相关参数
private SourcingType sourcingType = SourcingType.MYSQL; // 数据来源类型
private String localBinlogDirectory; // 本地localBinlog目录
private HAMode haMode = HAMode.HEARTBEAT; // ha机制
// 网络链接参数
private Integer port = 11111; // 服务端口,独立运行时需要配置
private Integer defaultConnectionTimeoutInSeconds = 30; // sotimeout
private Integer receiveBufferSize = 64 * 1024;
private Integer sendBufferSize = 64 * 1024;
// 编码信息
private Byte connectionCharsetNumber = (byte) 33;
private String connectionCharset = "UTF-8";
// 数据库信息
private List<InetSocketAddress> dbAddresses; // 数据库链接信息
private List<List<DataSourcing>> groupDbAddresses; // 数据库链接信息,包含多组信息
private String dbUsername; // 数据库用户
private String dbPassword; // 数据库密码
// binlog链接信息
private IndexMode indexMode;
private List<String> positions; // 数据库positions信息
private String defaultDatabaseName; // 默认链接的数据库schmea
private Long slaveId; // 链接到mysql的slaveId
private Integer fallbackIntervalInSeconds = 60; // 数据库发生切换查找时回退的时间
// 心跳检查信息
private Boolean detectingEnable = true; // 是否开启心跳语句
private Boolean heartbeatHaEnable = false; // 是否开启基于心跳检查的ha功能
private String detectingSQL; // 心跳sql
private Integer detectingIntervalInSeconds = 3; // 检测频率
private Integer detectingTimeoutThresholdInSeconds = 30; // 心跳超时时间
private Integer detectingRetryTimes = 3; // 心跳检查重试次数
// tddl/diamond 配置信息
private String app;
private String group;
// media配置信息
private String mediaGroup;
// metaq 存储配置信息
private String metaqStoreUri;
// ddl同步支持,隔离dml/ddl
private Boolean ddlIsolation = Boolean.FALSE; // 是否将ddl单条返回
private Boolean filterTableError = Boolean.FALSE; // 是否忽略表解析异常
private String blackFilter = null; // 匹配黑名单,忽略解析
// ================================== 兼容字段处理
private InetSocketAddress masterAddress; // 主库信息
private String masterUsername; // 帐号
private String masterPassword; // 密码
private InetSocketAddress standbyAddress; // 备库信息
private String standbyUsername; // 帐号
private String standbyPassword;
private String masterLogfileName = null; // master起始位置
private Long masterLogfileOffest = null;
private Long masterTimestamp = null;
private String standbyLogfileName = null; // standby起始位置
private Long standbyLogfileOffest = null;
private Long standbyTimestamp = null;
public static enum RunMode {
/** 嵌入式 */
EMBEDDED,
/** 服务式 */
SERVICE;
public boolean isEmbedded() {
return this.equals(RunMode.EMBEDDED);
}
public boolean isService() {
return this.equals(RunMode.SERVICE);
}
}
public static enum ClusterMode {
/** 嵌入式 */
STANDALONE,
/** 冷备 */
STANDBY,
/** 热备 */
ACTIVE;
public boolean isStandalone() {
return this.equals(ClusterMode.STANDALONE);
}
public boolean isStandby() {
return this.equals(ClusterMode.STANDBY);
}
public boolean isActive() {
return this.equals(ClusterMode.ACTIVE);
}
}
public static enum HAMode {
/** 心跳检测 */
HEARTBEAT,
/** otter media */
MEDIA;
public boolean isHeartBeat() {
return this.equals(HAMode.HEARTBEAT);
}
public boolean isMedia() {
return this.equals(HAMode.MEDIA);
}
}
public static enum StorageMode {
/** 内存存储模式 */
MEMORY,
/** 文件存储模式 */
FILE,
/** 混合模式,内存+文件 */
MIXED;
public boolean isMemory() {
return this.equals(StorageMode.MEMORY);
}
public boolean isFile() {
return this.equals(StorageMode.FILE);
}
public boolean isMixed() {
return this.equals(StorageMode.MIXED);
}
}
public static enum StorageScavengeMode {
/** 在存储满的时候触发 */
ON_FULL,
/** 在每次有ack请求时触发 */
ON_ACK,
/** 定时触发,需要外部控制 */
ON_SCHEDULE,
/** 不做任何操作,由外部进行清理 */
NO_OP;
public boolean isOnFull() {
return this.equals(StorageScavengeMode.ON_FULL);
}
public boolean isOnAck() {
return this.equals(StorageScavengeMode.ON_ACK);
}
public boolean isOnSchedule() {
return this.equals(StorageScavengeMode.ON_SCHEDULE);
}
public boolean isNoop() {
return this.equals(StorageScavengeMode.NO_OP);
}
}
public static enum SourcingType {
/** mysql DB */
MYSQL,
/** localBinLog */
LOCALBINLOG,
/** oracle DB */
ORACLE,
/** 多库合并模式 */
GROUP;
public boolean isMysql() {
return this.equals(SourcingType.MYSQL);
}
public boolean isLocalBinlog() {
return this.equals(SourcingType.LOCALBINLOG);
}
public boolean isOracle() {
return this.equals(SourcingType.ORACLE);
}
public boolean isGroup() {
return this.equals(SourcingType.GROUP);
}
}
public static enum MetaMode {
/** 内存存储模式 */
MEMORY,
/** 文件存储模式 */
ZOOKEEPER,
/** 混合模式,内存+文件 */
MIXED;
public boolean isMemory() {
return this.equals(MetaMode.MEMORY);
}
public boolean isZookeeper() {
return this.equals(MetaMode.ZOOKEEPER);
}
public boolean isMixed() {
return this.equals(MetaMode.MIXED);
}
}
public static enum IndexMode {
/** 内存存储模式 */
MEMORY,
/** 文件存储模式 */
ZOOKEEPER,
/** 混合模式,内存+文件 */
MIXED,
/** 基于meta信息 */
META,
/** 基于内存+meta的failback实现 */
MEMORY_META_FAILBACK;
public boolean isMemory() {
return this.equals(IndexMode.MEMORY);
}
public boolean isZookeeper() {
return this.equals(IndexMode.ZOOKEEPER);
}
public boolean isMixed() {
return this.equals(IndexMode.MIXED);
}
public boolean isMeta() {
return this.equals(IndexMode.META);
}
public boolean isMemoryMetaFailback() {
return this.equals(IndexMode.MEMORY_META_FAILBACK);
}
}
public static enum BatchMode {
/** 对象数量 */
ITEMSIZE,
/** 内存大小 */
MEMSIZE;
public boolean isItemSize() {
return this == BatchMode.ITEMSIZE;
}
public boolean isMemSize() {
return this == BatchMode.MEMSIZE;
}
}
/**
* 数据来源描述
*
* @author jianghang 2012-12-26 上午11:05:20
* @version 4.1.5
*/
public static class DataSourcing implements Serializable {
private static final long serialVersionUID = -1770648468678085234L;
private SourcingType type;
private InetSocketAddress dbAddress;
public DataSourcing(){
}
public DataSourcing(SourcingType type, InetSocketAddress dbAddress){
this.type = type;
this.dbAddress = dbAddress;
}
public SourcingType getType() {
return type;
}
public void setType(SourcingType type) {
this.type = type;
}
public InetSocketAddress getDbAddress() {
return dbAddress;
}
public void setDbAddress(InetSocketAddress dbAddress) {
this.dbAddress = dbAddress;
}
}
public Long getCanalId() {
return canalId;
}
public void setCanalId(Long canalId) {
this.canalId = canalId;
}
public RunMode getRunMode() {
return runMode;
}
public void setRunMode(RunMode runMode) {
this.runMode = runMode;
}
public ClusterMode getClusterMode() {
return clusterMode;
}
public void setClusterMode(ClusterMode clusterMode) {
this.clusterMode = clusterMode;
}
public List<String> getZkClusters() {
return zkClusters;
}
public void setZkClusters(List<String> zkClusters) {
this.zkClusters = zkClusters;
}
public MetaMode getMetaMode() {
return metaMode;
}
public void setMetaMode(MetaMode metaMode) {
this.metaMode = metaMode;
}
public StorageMode getStorageMode() {
return storageMode;
}
public void setStorageMode(StorageMode storageMode) {
this.storageMode = storageMode;
}
public Integer getMemoryStorageBufferSize() {
return memoryStorageBufferSize;
}
public void setMemoryStorageBufferSize(Integer memoryStorageBufferSize) {
this.memoryStorageBufferSize = memoryStorageBufferSize;
}
public String getFileStorageDirectory() {
return fileStorageDirectory;
}
public void setFileStorageDirectory(String fileStorageDirectory) {
this.fileStorageDirectory = fileStorageDirectory;
}
public Integer getFileStorageStoreCount() {
return fileStorageStoreCount;
}
public void setFileStorageStoreCount(Integer fileStorageStoreCount) {
this.fileStorageStoreCount = fileStorageStoreCount;
}
public Integer getFileStorageRollverCount() {
return fileStorageRollverCount;
}
public void setFileStorageRollverCount(Integer fileStorageRollverCount) {
this.fileStorageRollverCount = fileStorageRollverCount;
}
public Integer getFileStoragePercentThresold() {
return fileStoragePercentThresold;
}
public void setFileStoragePercentThresold(Integer fileStoragePercentThresold) {
this.fileStoragePercentThresold = fileStoragePercentThresold;
}
public SourcingType getSourcingType() {
return sourcingType;
}
public void setSourcingType(SourcingType sourcingType) {
this.sourcingType = sourcingType;
}
public String getLocalBinlogDirectory() {
return localBinlogDirectory;
}
public void setLocalBinlogDirectory(String localBinlogDirectory) {
this.localBinlogDirectory = localBinlogDirectory;
}
public HAMode getHaMode() {
return haMode;
}
public void setHaMode(HAMode haMode) {
this.haMode = haMode;
}
public Integer getPort() {
return port;
}
public void setPort(Integer port) {
this.port = port;
}
public Integer getDefaultConnectionTimeoutInSeconds() {
return defaultConnectionTimeoutInSeconds;
}
public void setDefaultConnectionTimeoutInSeconds(Integer defaultConnectionTimeoutInSeconds) {
this.defaultConnectionTimeoutInSeconds = defaultConnectionTimeoutInSeconds;
}
public Integer getReceiveBufferSize() {
return receiveBufferSize;
}
public void setReceiveBufferSize(Integer receiveBufferSize) {
this.receiveBufferSize = receiveBufferSize;
}
public Integer getSendBufferSize() {
return sendBufferSize;
}
public void setSendBufferSize(Integer sendBufferSize) {
this.sendBufferSize = sendBufferSize;
}
public Byte getConnectionCharsetNumber() {
return connectionCharsetNumber;
}
public void setConnectionCharsetNumber(Byte connectionCharsetNumber) {
this.connectionCharsetNumber = connectionCharsetNumber;
}
public String getConnectionCharset() {
return connectionCharset;
}
public void setConnectionCharset(String connectionCharset) {
this.connectionCharset = connectionCharset;
}
public IndexMode getIndexMode() {
return indexMode;
}
public void setIndexMode(IndexMode indexMode) {
this.indexMode = indexMode;
}
public String getDefaultDatabaseName() {
return defaultDatabaseName;
}
public void setDefaultDatabaseName(String defaultDatabaseName) {
this.defaultDatabaseName = defaultDatabaseName;
}
public Long getSlaveId() {
return slaveId;
}
public void setSlaveId(Long slaveId) {
this.slaveId = slaveId;
}
public Boolean getDetectingEnable() {
return detectingEnable;
}
public void setDetectingEnable(Boolean detectingEnable) {
this.detectingEnable = detectingEnable;
}
public String getDetectingSQL() {
return detectingSQL;
}
public void setDetectingSQL(String detectingSQL) {
this.detectingSQL = detectingSQL;
}
public Integer getDetectingIntervalInSeconds() {
return detectingIntervalInSeconds;
}
public void setDetectingIntervalInSeconds(Integer detectingIntervalInSeconds) {
this.detectingIntervalInSeconds = detectingIntervalInSeconds;
}
public Integer getDetectingTimeoutThresholdInSeconds() {
return detectingTimeoutThresholdInSeconds;
}
public void setDetectingTimeoutThresholdInSeconds(Integer detectingTimeoutThresholdInSeconds) {
this.detectingTimeoutThresholdInSeconds = detectingTimeoutThresholdInSeconds;
}
public Integer getDetectingRetryTimes() {
return detectingRetryTimes;
}
public void setDetectingRetryTimes(Integer detectingRetryTimes) {
this.detectingRetryTimes = detectingRetryTimes;
}
public StorageScavengeMode getStorageScavengeMode() {
return storageScavengeMode;
}
public void setStorageScavengeMode(StorageScavengeMode storageScavengeMode) {
this.storageScavengeMode = storageScavengeMode;
}
public String getScavengeSchdule() {
return scavengeSchdule;
}
public void setScavengeSchdule(String scavengeSchdule) {
this.scavengeSchdule = scavengeSchdule;
}
public String getApp() {
return app;
}
public String getGroup() {
return group;
}
public void setApp(String app) {
this.app = app;
}
public void setGroup(String group) {
this.group = group;
}
public String getMetaqStoreUri() {
return metaqStoreUri;
}
public void setMetaqStoreUri(String metaqStoreUri) {
this.metaqStoreUri = metaqStoreUri;
}
public Integer getTransactionSize() {
return transactionSize != null ? transactionSize : 1024;
}
public void setTransactionSize(Integer transactionSize) {
this.transactionSize = transactionSize;
}
public List<InetSocketAddress> getDbAddresses() {
if (dbAddresses == null) {
dbAddresses = new ArrayList<InetSocketAddress>();
if (masterAddress != null) {
dbAddresses.add(masterAddress);
}
if (standbyAddress != null) {
dbAddresses.add(standbyAddress);
}
}
return dbAddresses;
}
public List<List<DataSourcing>> getGroupDbAddresses() {
if (groupDbAddresses == null) {
groupDbAddresses = new ArrayList<List<DataSourcing>>();
if (dbAddresses != null) {
for (InetSocketAddress address : dbAddresses) {
List<DataSourcing> groupAddresses = new ArrayList<DataSourcing>();
groupAddresses.add(new DataSourcing(sourcingType, address));
groupDbAddresses.add(groupAddresses);
}
} else {
if (masterAddress != null) {
List<DataSourcing> groupAddresses = new ArrayList<DataSourcing>();
groupAddresses.add(new DataSourcing(sourcingType, masterAddress));
groupDbAddresses.add(groupAddresses);
}
if (standbyAddress != null) {
List<DataSourcing> groupAddresses = new ArrayList<DataSourcing>();
groupAddresses.add(new DataSourcing(sourcingType, standbyAddress));
groupDbAddresses.add(groupAddresses);
}
}
}
return groupDbAddresses;
}
public void setGroupDbAddresses(List<List<DataSourcing>> groupDbAddresses) {
this.groupDbAddresses = groupDbAddresses;
}
public void setDbAddresses(List<InetSocketAddress> dbAddresses) {
this.dbAddresses = dbAddresses;
}
public String getDbUsername() {
if (dbUsername == null) {
dbUsername = (masterUsername != null ? masterUsername : standbyUsername);
}
return dbUsername;
}
public void setDbUsername(String dbUsername) {
this.dbUsername = dbUsername;
}
public String getDbPassword() {
if (dbPassword == null) {
dbPassword = (masterPassword != null ? masterPassword : standbyPassword);
}
return dbPassword;
}
public void setDbPassword(String dbPassword) {
this.dbPassword = dbPassword;
}
public List<String> getPositions() {
if (positions == null) {
positions = new ArrayList<String>();
String masterPosition = buildPosition(masterLogfileName, masterLogfileOffest, masterTimestamp);
if (masterPosition != null) {
positions.add(masterPosition);
}
String standbyPosition = buildPosition(standbyLogfileName, standbyLogfileOffest, standbyTimestamp);
if (standbyPosition != null) {
positions.add(standbyPosition);
}
}
return positions;
}
public void setPositions(List<String> positions) {
this.positions = positions;
}
// ===========================兼容字段
private String buildPosition(String journalName, Long position, Long timestamp) {
StringBuilder masterBuilder = new StringBuilder();
if (StringUtils.isNotEmpty(journalName) || position != null || timestamp != null) {
masterBuilder.append('{');
if (StringUtils.isNotEmpty(journalName)) {
masterBuilder.append("\"journalName\":\"").append(journalName).append("\"");
}
if (position != null) {
if (masterBuilder.length() > 1) {
masterBuilder.append(",");
}
masterBuilder.append("\"position\":").append(position);
}
if (timestamp != null) {
if (masterBuilder.length() > 1) {
masterBuilder.append(",");
}
masterBuilder.append("\"timestamp\":").append(timestamp);
}
masterBuilder.append('}');
return masterBuilder.toString();
} else {
return null;
}
}
public void setMasterUsername(String masterUsername) {
this.masterUsername = masterUsername;
}
public void setMasterPassword(String masterPassword) {
this.masterPassword = masterPassword;
}
public void setStandbyAddress(InetSocketAddress standbyAddress) {
this.standbyAddress = standbyAddress;
}
public void setStandbyUsername(String standbyUsername) {
this.standbyUsername = standbyUsername;
}
public void setStandbyPassword(String standbyPassword) {
this.standbyPassword = standbyPassword;
}
public void setMasterLogfileName(String masterLogfileName) {
this.masterLogfileName = masterLogfileName;
}
public void setMasterLogfileOffest(Long masterLogfileOffest) {
this.masterLogfileOffest = masterLogfileOffest;
}
public void setMasterTimestamp(Long masterTimestamp) {
this.masterTimestamp = masterTimestamp;
}
public void setStandbyLogfileName(String standbyLogfileName) {
this.standbyLogfileName = standbyLogfileName;
}
public void setStandbyLogfileOffest(Long standbyLogfileOffest) {
this.standbyLogfileOffest = standbyLogfileOffest;
}
public void setStandbyTimestamp(Long standbyTimestamp) {
this.standbyTimestamp = standbyTimestamp;
}
public void setMasterAddress(InetSocketAddress masterAddress) {
this.masterAddress = masterAddress;
}
public Integer getFallbackIntervalInSeconds() {
return fallbackIntervalInSeconds == null ? 60 : fallbackIntervalInSeconds;
}
public void setFallbackIntervalInSeconds(Integer fallbackIntervalInSeconds) {
this.fallbackIntervalInSeconds = fallbackIntervalInSeconds;
}
public Boolean getHeartbeatHaEnable() {
return heartbeatHaEnable == null ? false : heartbeatHaEnable;
}
public void setHeartbeatHaEnable(Boolean heartbeatHaEnable) {
this.heartbeatHaEnable = heartbeatHaEnable;
}
public BatchMode getStorageBatchMode() {
return storageBatchMode == null ? BatchMode.MEMSIZE : storageBatchMode;
}
public void setStorageBatchMode(BatchMode storageBatchMode) {
this.storageBatchMode = storageBatchMode;
}
public Integer getMemoryStorageBufferMemUnit() {
return memoryStorageBufferMemUnit == null ? 1024 : memoryStorageBufferMemUnit;
}
public void setMemoryStorageBufferMemUnit(Integer memoryStorageBufferMemUnit) {
this.memoryStorageBufferMemUnit = memoryStorageBufferMemUnit;
}
public String getMediaGroup() {
return mediaGroup;
}
public void setMediaGroup(String mediaGroup) {
this.mediaGroup = mediaGroup;
}
public Long getZkClusterId() {
return zkClusterId;
}
public void setZkClusterId(Long zkClusterId) {
this.zkClusterId = zkClusterId;
}
public Boolean getDdlIsolation() {
return ddlIsolation == null ? false : ddlIsolation;
}
public void setDdlIsolation(Boolean ddlIsolation) {
this.ddlIsolation = ddlIsolation;
}
public Boolean getFilterTableError() {
return filterTableError == null ? false : filterTableError;
}
public void setFilterTableError(Boolean filterTableError) {
this.filterTableError = filterTableError;
}
public String getBlackFilter() {
return blackFilter;
}
public void setBlackFilter(String blackFilter) {
this.blackFilter = blackFilter;
}
public String toString() {
return ToStringBuilder.reflectionToString(this, CanalToStringStyle.DEFAULT_STYLE);
}
}

View File

@@ -0,0 +1,22 @@
package com.alibaba.otter.canal.instance.manager.model;
/**
* 运行状态
*
* @author jianghang 2012-7-13 下午12:54:13
* @version 1.0.0
*/
public enum CanalStatus {
/** 启动 */
START,
/** 停止 */
STOP;
public boolean isStart() {
return this.equals(CanalStatus.START);
}
public boolean isStop() {
return this.equals(CanalStatus.STOP);
}
}