mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
format & import
This commit is contained in:
@@ -3,8 +3,6 @@ package com.alibaba.otter.canal.client.adapter;
|
|||||||
import com.alibaba.otter.canal.client.adapter.support.CanalOuterAdapterConfiguration;
|
import com.alibaba.otter.canal.client.adapter.support.CanalOuterAdapterConfiguration;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.Dml;
|
import com.alibaba.otter.canal.client.adapter.support.Dml;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.SPI;
|
import com.alibaba.otter.canal.client.adapter.support.SPI;
|
||||||
import com.alibaba.otter.canal.protocol.FlatMessage;
|
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 外部适配器接口
|
* 外部适配器接口
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ public class CanalClientConfig {
|
|||||||
|
|
||||||
private Boolean flatMessage = true;
|
private Boolean flatMessage = true;
|
||||||
|
|
||||||
|
|
||||||
private List<CanalInstance> canalInstances;
|
private List<CanalInstance> canalInstances;
|
||||||
|
|
||||||
public String getCanalServerHost() {
|
public String getCanalServerHost() {
|
||||||
@@ -122,6 +121,7 @@ public class CanalClientConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class MQTopic {
|
public static class MQTopic {
|
||||||
|
|
||||||
private String mqMode;
|
private String mqMode;
|
||||||
|
|
||||||
private String topic;
|
private String topic;
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ public class Dml implements Serializable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Dml{" + "database='" + database + '\'' + ", table='" + table + '\'' + ", type='" + type + '\'' + ", ts="
|
return "Dml{" + "database='" + database + '\'' + ", table='" + table + '\'' + ", type='" + type + '\''
|
||||||
+ ts + ", sql='" + sql + '\'' + ", data=" + data + ", old=" + old + '}';
|
+ ", ts=" + ts + ", sql='" + sql + '\'' + ", data=" + data + ", old=" + old + '}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,22 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.support;
|
package com.alibaba.otter.canal.client.adapter.support;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FilenameFilter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -21,8 +32,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
public class ExtensionLoader<T> {
|
public class ExtensionLoader<T> {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory
|
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
|
||||||
.getLogger(ExtensionLoader.class);
|
|
||||||
|
|
||||||
private static final String SERVICES_DIRECTORY = "META-INF/services/";
|
private static final String SERVICES_DIRECTORY = "META-INF/services/";
|
||||||
|
|
||||||
@@ -30,8 +40,7 @@ public class ExtensionLoader<T> {
|
|||||||
|
|
||||||
private static final String DEFAULT_CLASSLOADER_POLICY = "internal";
|
private static final String DEFAULT_CLASSLOADER_POLICY = "internal";
|
||||||
|
|
||||||
private static final Pattern NAME_SEPARATOR = Pattern
|
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
|
||||||
.compile("\\s*[,]+\\s*");
|
|
||||||
|
|
||||||
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -262,8 +271,7 @@ public class ExtensionLoader<T> {
|
|||||||
return instance;
|
return instance;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
|
throw new IllegalStateException("Extension instance(name: " + name + ", class: " + type
|
||||||
+ ") could not be instantiated: " + t.getMessage(),
|
+ ") could not be instantiated: " + t.getMessage(), t);
|
||||||
t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,8 +279,8 @@ public class ExtensionLoader<T> {
|
|||||||
if (type == null) throw new IllegalArgumentException("Extension type == null");
|
if (type == null) throw new IllegalArgumentException("Extension type == null");
|
||||||
if (name == null) throw new IllegalArgumentException("Extension name == null");
|
if (name == null) throw new IllegalArgumentException("Extension name == null");
|
||||||
Class<?> clazz = getExtensionClasses().get(name);
|
Class<?> clazz = getExtensionClasses().get(name);
|
||||||
if (clazz == null)
|
if (clazz == null) throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName()
|
||||||
throw new IllegalStateException("No such extension \"" + name + "\" for " + type.getName() + "!");
|
+ "!");
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,10 +304,17 @@ public class ExtensionLoader<T> {
|
|||||||
throw new IllegalStateException("failed to get class loader resource");
|
throw new IllegalStateException("failed to get class loader resource");
|
||||||
}
|
}
|
||||||
String dirtyPath = url.toString();
|
String dirtyPath = url.toString();
|
||||||
String jarPath = dirtyPath.replaceAll("^.*file:/", ""); // removes file:/ and everything before it
|
String jarPath = dirtyPath.replaceAll("^.*file:/", ""); // removes
|
||||||
jarPath = jarPath.replaceAll("jar!.*", "jar"); // removes everything after .jar, if .jar exists in dirtyPath
|
// file:/ and
|
||||||
jarPath = jarPath.replaceAll("%20", " "); // necessary if path has spaces within
|
// everything
|
||||||
if (!jarPath.endsWith(".jar")) { // this is needed if you plan to run the app using Spring Tools Suit play
|
// before it
|
||||||
|
jarPath = jarPath.replaceAll("jar!.*", "jar"); // removes everything
|
||||||
|
// after .jar, if .jar
|
||||||
|
// exists in dirtyPath
|
||||||
|
jarPath = jarPath.replaceAll("%20", " "); // necessary if path has
|
||||||
|
// spaces within
|
||||||
|
if (!jarPath.endsWith(".jar")) { // this is needed if you plan to run
|
||||||
|
// the app using Spring Tools Suit play
|
||||||
// button.
|
// button.
|
||||||
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
|
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
|
||||||
}
|
}
|
||||||
@@ -327,8 +342,8 @@ public class ExtensionLoader<T> {
|
|||||||
logger.info("extension classpath dir: " + dir);
|
logger.info("extension classpath dir: " + dir);
|
||||||
File externalLibDir = new File(dir);
|
File externalLibDir = new File(dir);
|
||||||
if (!externalLibDir.exists()) {
|
if (!externalLibDir.exists()) {
|
||||||
externalLibDir = new File(
|
externalLibDir = new File(File.separator + this.getJarDirectoryPath() + File.separator + "canal_client"
|
||||||
File.separator + this.getJarDirectoryPath() + File.separator + "canal_client" + File.separator + "lib");
|
+ File.separator + "lib");
|
||||||
}
|
}
|
||||||
if (externalLibDir.exists()) {
|
if (externalLibDir.exists()) {
|
||||||
File[] files = externalLibDir.listFiles(new FilenameFilter() {
|
File[] files = externalLibDir.listFiles(new FilenameFilter() {
|
||||||
@@ -363,7 +378,8 @@ public class ExtensionLoader<T> {
|
|||||||
if (name.startsWith("java.") || name.startsWith("org.slf4j.")
|
if (name.startsWith("java.") || name.startsWith("org.slf4j.")
|
||||||
|| name.startsWith("org.apache.logging")
|
|| name.startsWith("org.apache.logging")
|
||||||
|| name.startsWith("org.apache.commons.logging.")) {
|
|| name.startsWith("org.apache.commons.logging.")) {
|
||||||
// || name.startsWith("org.apache.hadoop.")) {
|
// || name.startsWith("org.apache.hadoop."))
|
||||||
|
// {
|
||||||
c = super.loadClass(name);
|
c = super.loadClass(name);
|
||||||
}
|
}
|
||||||
if (c != null) return c;
|
if (c != null) return c;
|
||||||
@@ -386,7 +402,8 @@ public class ExtensionLoader<T> {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
|
Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[2];
|
||||||
|
|
||||||
tmp[0] = findResources(name); // local class path first
|
tmp[0] = findResources(name); // local class
|
||||||
|
// path first
|
||||||
// tmp[1] = super.getResources(name);
|
// tmp[1] = super.getResources(name);
|
||||||
|
|
||||||
return new CompoundEnumeration<>(tmp);
|
return new CompoundEnumeration<>(tmp);
|
||||||
@@ -474,12 +491,16 @@ public class ExtensionLoader<T> {
|
|||||||
}
|
}
|
||||||
if (line.length() > 0) {
|
if (line.length() > 0) {
|
||||||
Class<?> clazz = classLoader.loadClass(line);
|
Class<?> clazz = classLoader.loadClass(line);
|
||||||
// Class<?> clazz = Class.forName(line, true, classLoader);
|
// Class<?> clazz =
|
||||||
|
// Class.forName(line, true,
|
||||||
|
// classLoader);
|
||||||
if (!type.isAssignableFrom(clazz)) {
|
if (!type.isAssignableFrom(clazz)) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("Error when load extension class(interface: "
|
||||||
"Error when load extension class(interface: " + type
|
+ type
|
||||||
+ ", class line: " + clazz.getName()
|
+ ", class line: "
|
||||||
+ "), class " + clazz.getName()
|
+ clazz.getName()
|
||||||
|
+ "), class "
|
||||||
|
+ clazz.getName()
|
||||||
+ "is not subtype of interface.");
|
+ "is not subtype of interface.");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@@ -497,9 +518,9 @@ public class ExtensionLoader<T> {
|
|||||||
extensionClasses.put(n, clazz);
|
extensionClasses.put(n, clazz);
|
||||||
} else if (c != clazz) {
|
} else if (c != clazz) {
|
||||||
cachedNames.remove(clazz);
|
cachedNames.remove(clazz);
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException("Duplicate extension "
|
||||||
"Duplicate extension " + type.getName() + " name "
|
+ type.getName()
|
||||||
+ n + " on "
|
+ " name " + n + " on "
|
||||||
+ c.getName() + " and "
|
+ c.getName() + " and "
|
||||||
+ clazz.getName());
|
+ clazz.getName());
|
||||||
}
|
}
|
||||||
@@ -509,9 +530,12 @@ public class ExtensionLoader<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
IllegalStateException e = new IllegalStateException(
|
IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: "
|
||||||
"Failed to load extension class(interface: " + type + ", class line: "
|
+ type
|
||||||
+ line + ") in " + url
|
+ ", class line: "
|
||||||
|
+ line
|
||||||
|
+ ") in "
|
||||||
|
+ url
|
||||||
+ ", cause: "
|
+ ", cause: "
|
||||||
+ t.getMessage(),
|
+ t.getMessage(),
|
||||||
t);
|
t);
|
||||||
@@ -526,15 +550,13 @@ public class ExtensionLoader<T> {
|
|||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error("Exception when load extension class(interface: " + type + ", class file: " + url
|
logger.error("Exception when load extension class(interface: " + type + ", class file: " + url
|
||||||
+ ") in " + url,
|
+ ") in " + url, t);
|
||||||
t);
|
|
||||||
}
|
}
|
||||||
} // end of while urls
|
} // end of while urls
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error(
|
logger.error("Exception when load extension class(interface: " + type + ", description file: " + fileName
|
||||||
"Exception when load extension class(interface: " + type + ", description file: " + fileName + ").",
|
+ ").", t);
|
||||||
t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,11 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.support;
|
package com.alibaba.otter.canal.client.adapter.support;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||||
import com.alibaba.otter.canal.protocol.FlatMessage;
|
import com.alibaba.otter.canal.protocol.FlatMessage;
|
||||||
@@ -81,8 +86,7 @@ public class MessageUtil {
|
|||||||
Map<String, Object> rowOld = new LinkedHashMap<>();
|
Map<String, Object> rowOld = new LinkedHashMap<>();
|
||||||
for (CanalEntry.Column column : rowData.getBeforeColumnsList()) {
|
for (CanalEntry.Column column : rowData.getBeforeColumnsList()) {
|
||||||
if (updateSet.contains(column.getName())) {
|
if (updateSet.contains(column.getName())) {
|
||||||
rowOld.put(column.getName(),
|
rowOld.put(column.getName(), JdbcTypeUtil.typeConvert(column.getName(),
|
||||||
JdbcTypeUtil.typeConvert(column.getName(),
|
|
||||||
column.getValue(),
|
column.getValue(),
|
||||||
column.getSqlType(),
|
column.getSqlType(),
|
||||||
column.getMysqlType()));
|
column.getMysqlType()));
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.support;
|
package com.alibaba.otter.canal.client.adapter.support;
|
||||||
|
|
||||||
import java.lang.annotation.*;
|
import java.lang.annotation.Documented;
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.protocol.FlatMessage;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
import org.apache.hadoop.hbase.HBaseConfiguration;
|
import org.apache.hadoop.hbase.HBaseConfiguration;
|
||||||
@@ -17,9 +16,7 @@ import com.alibaba.otter.canal.client.adapter.hbase.config.MappingConfigLoader;
|
|||||||
import com.alibaba.otter.canal.client.adapter.hbase.service.HbaseSyncService;
|
import com.alibaba.otter.canal.client.adapter.hbase.service.HbaseSyncService;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.CanalOuterAdapterConfiguration;
|
import com.alibaba.otter.canal.client.adapter.support.CanalOuterAdapterConfiguration;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.Dml;
|
import com.alibaba.otter.canal.client.adapter.support.Dml;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.MessageUtil;
|
|
||||||
import com.alibaba.otter.canal.client.adapter.support.SPI;
|
import com.alibaba.otter.canal.client.adapter.support.SPI;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HBase外部适配器
|
* HBase外部适配器
|
||||||
@@ -45,8 +42,7 @@ public class HbaseAdapter implements CanalOuterAdapter {
|
|||||||
mappingConfigCache = new HashMap<>();
|
mappingConfigCache = new HashMap<>();
|
||||||
for (MappingConfig mappingConfig : hbaseMapping.values()) {
|
for (MappingConfig mappingConfig : hbaseMapping.values()) {
|
||||||
mappingConfigCache.put(mappingConfig.getHbaseOrm().getDatabase() + "-"
|
mappingConfigCache.put(mappingConfig.getHbaseOrm().getDatabase() + "-"
|
||||||
+ mappingConfig.getHbaseOrm().getTable(),
|
+ mappingConfig.getHbaseOrm().getTable(), mappingConfig);
|
||||||
mappingConfig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.hbase.config;
|
package com.alibaba.otter.canal.client.adapter.hbase.config;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HBase表映射配置
|
* HBase表映射配置
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.hbase.service;
|
package com.alibaba.otter.canal.client.adapter.hbase.service;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.hadoop.hbase.client.Connection;
|
import org.apache.hadoop.hbase.client.Connection;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
@@ -8,7 +12,12 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.adapter.hbase.config.MappingConfig;
|
import com.alibaba.otter.canal.client.adapter.hbase.config.MappingConfig;
|
||||||
import com.alibaba.otter.canal.client.adapter.hbase.support.*;
|
import com.alibaba.otter.canal.client.adapter.hbase.support.HRow;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.hbase.support.HbaseTemplate;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.hbase.support.PhType;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.hbase.support.PhTypeUtil;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.hbase.support.Type;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.hbase.support.TypeUtil;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.Dml;
|
import com.alibaba.otter.canal.client.adapter.support.Dml;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,7 +72,8 @@ public class HbaseSyncService {
|
|||||||
MappingConfig.HbaseOrm hbaseOrm = config.getHbaseOrm();
|
MappingConfig.HbaseOrm hbaseOrm = config.getHbaseOrm();
|
||||||
|
|
||||||
// if (!validHTable(config)) {
|
// if (!validHTable(config)) {
|
||||||
// logger.error("HBase table '{}' not exists", hbaseOrm.getHbaseTable());
|
// logger.error("HBase table '{}' not exists",
|
||||||
|
// hbaseOrm.getHbaseTable());
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
int i = 1;
|
int i = 1;
|
||||||
@@ -156,7 +166,8 @@ public class HbaseSyncService {
|
|||||||
MappingConfig.HbaseOrm hbaseOrm = config.getHbaseOrm();
|
MappingConfig.HbaseOrm hbaseOrm = config.getHbaseOrm();
|
||||||
|
|
||||||
// if (!validHTable(config)) {
|
// if (!validHTable(config)) {
|
||||||
// logger.error("HBase table '{}' not exists", hbaseOrm.getHbaseTable());
|
// logger.error("HBase table '{}' not exists",
|
||||||
|
// hbaseOrm.getHbaseTable());
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -248,7 +259,8 @@ public class HbaseSyncService {
|
|||||||
MappingConfig.HbaseOrm hbaseOrm = config.getHbaseOrm();
|
MappingConfig.HbaseOrm hbaseOrm = config.getHbaseOrm();
|
||||||
|
|
||||||
// if (!validHTable(config)) {
|
// if (!validHTable(config)) {
|
||||||
// logger.error("HBase table '{}' not exists", hbaseOrm.getHbaseTable());
|
// logger.error("HBase table '{}' not exists",
|
||||||
|
// hbaseOrm.getHbaseTable());
|
||||||
// return;
|
// return;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@@ -363,8 +375,7 @@ public class HbaseSyncService {
|
|||||||
* @param value 值
|
* @param value 值
|
||||||
* @return 复合字段rowKey
|
* @return 复合字段rowKey
|
||||||
*/
|
*/
|
||||||
private static byte[] typeConvert(MappingConfig.ColumnItem columnItem, MappingConfig.HbaseOrm hbaseOrm,
|
private static byte[] typeConvert(MappingConfig.ColumnItem columnItem, MappingConfig.HbaseOrm hbaseOrm, Object value) {
|
||||||
Object value) {
|
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,11 @@ import java.util.Set;
|
|||||||
import org.apache.hadoop.hbase.HColumnDescriptor;
|
import org.apache.hadoop.hbase.HColumnDescriptor;
|
||||||
import org.apache.hadoop.hbase.HTableDescriptor;
|
import org.apache.hadoop.hbase.HTableDescriptor;
|
||||||
import org.apache.hadoop.hbase.TableName;
|
import org.apache.hadoop.hbase.TableName;
|
||||||
import org.apache.hadoop.hbase.client.*;
|
import org.apache.hadoop.hbase.client.Connection;
|
||||||
|
import org.apache.hadoop.hbase.client.Delete;
|
||||||
|
import org.apache.hadoop.hbase.client.HBaseAdmin;
|
||||||
|
import org.apache.hadoop.hbase.client.HTable;
|
||||||
|
import org.apache.hadoop.hbase.client.Put;
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|||||||
@@ -13,29 +13,13 @@ import java.util.Date;
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum PhType {
|
public enum PhType {
|
||||||
DEFAULT(-1, "VARCHAR"),
|
DEFAULT(-1, "VARCHAR"), UNSIGNED_INT(4, "UNSIGNED_INT"), UNSIGNED_LONG(8, "UNSIGNED_LONG"),
|
||||||
UNSIGNED_INT(4, "UNSIGNED_INT"),
|
UNSIGNED_TINYINT(1, "UNSIGNED_TINYINT"), UNSIGNED_SMALLINT(2, "UNSIGNED_SMALLINT"),
|
||||||
UNSIGNED_LONG(8, "UNSIGNED_LONG"),
|
UNSIGNED_FLOAT(4, "UNSIGNED_FLOAT"), UNSIGNED_DOUBLE(8, "UNSIGNED_DOUBLE"), INTEGER(4, "INTEGER"),
|
||||||
UNSIGNED_TINYINT(1, "UNSIGNED_TINYINT"),
|
BIGINT(8, "BIGINT"), TINYINT(1, "TINYINT"), SMALLINT(2, "SMALLINT"), FLOAT(4, "FLOAT"), DOUBLE(8, "DOUBLE"),
|
||||||
UNSIGNED_SMALLINT(2, "UNSIGNED_SMALLINT"),
|
DECIMAL(-1, "DECIMAL"), BOOLEAN(1, "BOOLEAN"), UNSIGNED_TIME(8, "UNSIGNED_TIME"),
|
||||||
UNSIGNED_FLOAT(4, "UNSIGNED_FLOAT"),
|
UNSIGNED_DATE(8, "UNSIGNED_DATE"), UNSIGNED_TIMESTAMP(12, "UNSIGNED_TIMESTAMP"), TIME(8, "TIME"), DATE(8, "DATE"),
|
||||||
UNSIGNED_DOUBLE(8, "UNSIGNED_DOUBLE"),
|
TIMESTAMP(12, "TIMESTAMP"), VARCHAR(-1, "VARCHAR"), VARBINARY(-1, "VARBINARY");
|
||||||
INTEGER(4, "INTEGER"),
|
|
||||||
BIGINT(8, "BIGINT"),
|
|
||||||
TINYINT(1, "TINYINT"),
|
|
||||||
SMALLINT(2, "SMALLINT"),
|
|
||||||
FLOAT(4, "FLOAT"),
|
|
||||||
DOUBLE(8, "DOUBLE"),
|
|
||||||
DECIMAL(-1, "DECIMAL"),
|
|
||||||
BOOLEAN(1, "BOOLEAN"),
|
|
||||||
UNSIGNED_TIME(8, "UNSIGNED_TIME"),
|
|
||||||
UNSIGNED_DATE(8, "UNSIGNED_DATE"),
|
|
||||||
UNSIGNED_TIMESTAMP(12, "UNSIGNED_TIMESTAMP"),
|
|
||||||
TIME(8, "TIME"),
|
|
||||||
DATE(8, "DATE"),
|
|
||||||
TIMESTAMP(12, "TIMESTAMP"),
|
|
||||||
VARCHAR(-1, "VARCHAR"),
|
|
||||||
VARBINARY(-1, "VARBINARY");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* -1:长度可变
|
* -1:长度可变
|
||||||
|
|||||||
@@ -169,7 +169,8 @@ public class PhTypeUtil {
|
|||||||
|
|
||||||
private static int encodeInt(int v, byte[] b, int o) {
|
private static int encodeInt(int v, byte[] b, int o) {
|
||||||
checkForSufficientLength(b, o, Bytes.SIZEOF_INT);
|
checkForSufficientLength(b, o, Bytes.SIZEOF_INT);
|
||||||
b[o + 0] = (byte) ((v >> 24) ^ 0x80); // Flip sign bit so that INTEGER is binary comparable
|
b[o + 0] = (byte) ((v >> 24) ^ 0x80); // Flip sign bit so that INTEGER
|
||||||
|
// is binary comparable
|
||||||
b[o + 1] = (byte) (v >> 16);
|
b[o + 1] = (byte) (v >> 16);
|
||||||
b[o + 2] = (byte) (v >> 8);
|
b[o + 2] = (byte) (v >> 8);
|
||||||
b[o + 3] = (byte) v;
|
b[o + 3] = (byte) v;
|
||||||
@@ -209,7 +210,8 @@ public class PhTypeUtil {
|
|||||||
|
|
||||||
private static int encodeLong(long v, byte[] b, int o) {
|
private static int encodeLong(long v, byte[] b, int o) {
|
||||||
checkForSufficientLength(b, o, Bytes.SIZEOF_LONG);
|
checkForSufficientLength(b, o, Bytes.SIZEOF_LONG);
|
||||||
b[o + 0] = (byte) ((v >> 56) ^ 0x80); // Flip sign bit so that INTEGER is binary comparable
|
b[o + 0] = (byte) ((v >> 56) ^ 0x80); // Flip sign bit so that INTEGER
|
||||||
|
// is binary comparable
|
||||||
b[o + 1] = (byte) (v >> 48);
|
b[o + 1] = (byte) (v >> 48);
|
||||||
b[o + 2] = (byte) (v >> 40);
|
b[o + 2] = (byte) (v >> 40);
|
||||||
b[o + 3] = (byte) (v >> 32);
|
b[o + 3] = (byte) (v >> 32);
|
||||||
@@ -255,7 +257,8 @@ public class PhTypeUtil {
|
|||||||
|
|
||||||
private static int encodeShort(short v, byte[] b, int o) {
|
private static int encodeShort(short v, byte[] b, int o) {
|
||||||
checkForSufficientLength(b, o, Bytes.SIZEOF_SHORT);
|
checkForSufficientLength(b, o, Bytes.SIZEOF_SHORT);
|
||||||
b[o + 0] = (byte) ((v >> 8) ^ 0x80); // Flip sign bit so that Short is binary comparable
|
b[o + 0] = (byte) ((v >> 8) ^ 0x80); // Flip sign bit so that Short is
|
||||||
|
// binary comparable
|
||||||
b[o + 1] = (byte) v;
|
b[o + 1] = (byte) v;
|
||||||
return Bytes.SIZEOF_SHORT;
|
return Bytes.SIZEOF_SHORT;
|
||||||
}
|
}
|
||||||
@@ -287,7 +290,8 @@ public class PhTypeUtil {
|
|||||||
|
|
||||||
private static int encodeByte(byte v, byte[] b, int o) {
|
private static int encodeByte(byte v, byte[] b, int o) {
|
||||||
checkForSufficientLength(b, o, Bytes.SIZEOF_BYTE);
|
checkForSufficientLength(b, o, Bytes.SIZEOF_BYTE);
|
||||||
b[o] = (byte) (v ^ 0x80); // Flip sign bit so that Short is binary comparable
|
b[o] = (byte) (v ^ 0x80); // Flip sign bit so that Short is binary
|
||||||
|
// comparable
|
||||||
return Bytes.SIZEOF_BYTE;
|
return Bytes.SIZEOF_BYTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +550,8 @@ public class PhTypeUtil {
|
|||||||
multiplyBy = 10;
|
multiplyBy = 10;
|
||||||
divideBy = BigInteger.TEN;
|
divideBy = BigInteger.TEN;
|
||||||
}
|
}
|
||||||
// Normalize the scale based on what is necessary to end up with a base 100
|
// Normalize the scale based on what is necessary to end up with a base
|
||||||
|
// 100
|
||||||
// decimal (i.e. 10.123e3)
|
// decimal (i.e. 10.123e3)
|
||||||
int digitOffset;
|
int digitOffset;
|
||||||
BigInteger compareAgainst;
|
BigInteger compareAgainst;
|
||||||
@@ -564,7 +569,8 @@ public class PhTypeUtil {
|
|||||||
if (length <= MAX_BIG_DECIMAL_BYTES) {
|
if (length <= MAX_BIG_DECIMAL_BYTES) {
|
||||||
result[--index] = NEG_TERMINAL_BYTE;
|
result[--index] = NEG_TERMINAL_BYTE;
|
||||||
} else {
|
} else {
|
||||||
// Adjust length and offset down because we don't have enough room
|
// Adjust length and offset down because we don't have enough
|
||||||
|
// room
|
||||||
length = MAX_BIG_DECIMAL_BYTES;
|
length = MAX_BIG_DECIMAL_BYTES;
|
||||||
index = offset + length;
|
index = offset + length;
|
||||||
}
|
}
|
||||||
@@ -593,8 +599,8 @@ public class PhTypeUtil {
|
|||||||
|
|
||||||
private static void checkForSufficientLength(byte[] b, int offset, int requiredLength) {
|
private static void checkForSufficientLength(byte[] b, int offset, int requiredLength) {
|
||||||
if (b.length < offset + requiredLength) {
|
if (b.length < offset + requiredLength) {
|
||||||
throw new RuntimeException(
|
throw new RuntimeException("Expected length of at least " + requiredLength + " bytes, but had "
|
||||||
"Expected length of at least " + requiredLength + " bytes, but had " + (b.length - offset));
|
+ (b.length - offset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,18 +11,8 @@ import java.util.Date;
|
|||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
public enum Type {
|
public enum Type {
|
||||||
DEFAULT("STRING"),
|
DEFAULT("STRING"), STRING("STRING"), INTEGER("INTEGER"), LONG("LONG"), SHORT("SHORT"), BOOLEAN("BOOLEAN"),
|
||||||
STRING("STRING"),
|
FLOAT("FLOAT"), DOUBLE("DOUBLE"), BIGDECIMAL("BIGDECIMAL"), DATE("DATE"), BYTE("BYTE"), BYTES("BYTES");
|
||||||
INTEGER("INTEGER"),
|
|
||||||
LONG("LONG"),
|
|
||||||
SHORT("SHORT"),
|
|
||||||
BOOLEAN("BOOLEAN"),
|
|
||||||
FLOAT("FLOAT"),
|
|
||||||
DOUBLE("DOUBLE"),
|
|
||||||
BIGDECIMAL("BIGDECIMAL"),
|
|
||||||
DATE("DATE"),
|
|
||||||
BYTE("BYTE"),
|
|
||||||
BYTES("BYTES");
|
|
||||||
|
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import com.alibaba.otter.canal.client.adapter.support.SPI;
|
|||||||
* @author machengyuan 2018-8-19 下午11:45:38
|
* @author machengyuan 2018-8-19 下午11:45:38
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
@SPI("logger") // logger参数对应CanalOuterAdapterConfiguration配置中的name
|
@SPI("logger")
|
||||||
|
// logger参数对应CanalOuterAdapterConfiguration配置中的name
|
||||||
public class LoggerAdapterExample implements CanalOuterAdapter {
|
public class LoggerAdapterExample implements CanalOuterAdapter {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.alibaba.otter.canal.client;
|
package com.alibaba.otter.canal.client;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.adapter.loader.CanalAdapterLoader;
|
import java.io.FileInputStream;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.CanalClientConfig;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
import com.alibaba.otter.canal.client.adapter.loader.CanalAdapterLoader;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.CanalClientConfig;
|
||||||
|
|
||||||
public class ClientLauncher {
|
public class ClientLauncher {
|
||||||
|
|
||||||
|
|||||||
@@ -131,25 +131,16 @@ public abstract class AbstractCanalAdapterWorker {
|
|||||||
|
|
||||||
protected void writeOut(Message message, String topic) {
|
protected void writeOut(Message message, String topic) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("topic: {} batchId: {} batchSize: {} ",
|
logger.debug("topic: {} batchId: {} batchSize: {} ", topic, message.getId(), message.getEntries().size());
|
||||||
topic,
|
|
||||||
message.getId(),
|
|
||||||
message.getEntries().size());
|
|
||||||
}
|
}
|
||||||
long begin = System.currentTimeMillis();
|
long begin = System.currentTimeMillis();
|
||||||
writeOut(message);
|
writeOut(message);
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
if ((System.currentTimeMillis() - begin) > 5 * 60 * 1000) {
|
if ((System.currentTimeMillis() - begin) > 5 * 60 * 1000) {
|
||||||
logger.error("topic: {} batchId {} elapsed time: {} ms",
|
logger.error("topic: {} batchId {} elapsed time: {} ms", topic, message.getId(), now - begin);
|
||||||
topic,
|
|
||||||
message.getId(),
|
|
||||||
now - begin);
|
|
||||||
}
|
}
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("topic: {} batchId {} elapsed time: {} ms",
|
logger.debug("topic: {} batchId {} elapsed time: {} ms", topic, message.getId(), now - begin);
|
||||||
topic,
|
|
||||||
message.getId(),
|
|
||||||
now - begin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +161,7 @@ public abstract class AbstractCanalAdapterWorker {
|
|||||||
}
|
}
|
||||||
logger.info("topic all connectors destroyed!");
|
logger.info("topic all connectors destroyed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void start();
|
public abstract void start();
|
||||||
|
|
||||||
public abstract void stop();
|
public abstract void stop();
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.loader;
|
package com.alibaba.otter.canal.client.adapter.loader;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.adapter.CanalOuterAdapter;
|
|
||||||
import com.alibaba.otter.canal.client.adapter.support.CanalClientConfig;
|
|
||||||
import com.alibaba.otter.canal.client.adapter.support.CanalOuterAdapterConfiguration;
|
|
||||||
import com.alibaba.otter.canal.client.adapter.support.ExtensionLoader;
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -12,10 +8,16 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.client.adapter.CanalOuterAdapter;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.CanalClientConfig;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.CanalOuterAdapterConfiguration;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.ExtensionLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MQ外部适配器的加载器
|
* MQ外部适配器的加载器
|
||||||
*
|
*
|
||||||
@@ -46,8 +48,14 @@ public class CanalAdapterLoader {
|
|||||||
throw new RuntimeException("Blank config property: canalInstances or canalMQTopics");
|
throw new RuntimeException("Blank config property: canalInstances or canalMQTopics");
|
||||||
}
|
}
|
||||||
|
|
||||||
loader = ExtensionLoader.getExtensionLoader(CanalOuterAdapter.class,
|
loader = ExtensionLoader.getExtensionLoader(CanalOuterAdapter.class, "" /*
|
||||||
"" /* TODO canalClientConfig.getClassloaderPolicy() */);
|
* TODO
|
||||||
|
* canalClientConfig
|
||||||
|
* .
|
||||||
|
* getClassloaderPolicy
|
||||||
|
* (
|
||||||
|
* )
|
||||||
|
*/);
|
||||||
|
|
||||||
String canalServerHost = this.canalClientConfig.getCanalServerHost();
|
String canalServerHost = this.canalClientConfig.getCanalServerHost();
|
||||||
SocketAddress sa = null;
|
SocketAddress sa = null;
|
||||||
@@ -94,24 +102,23 @@ public class CanalAdapterLoader {
|
|||||||
}
|
}
|
||||||
canalOuterAdapterGroups.add(canalOuterAdapters);
|
canalOuterAdapterGroups.add(canalOuterAdapters);
|
||||||
if (StringUtils.isBlank(topic.getMqMode()) || "rocketmq".equalsIgnoreCase(topic.getMqMode())) {
|
if (StringUtils.isBlank(topic.getMqMode()) || "rocketmq".equalsIgnoreCase(topic.getMqMode())) {
|
||||||
CanalAdapterRocketMQWorker rocketMQWorker = new CanalAdapterRocketMQWorker(
|
CanalAdapterRocketMQWorker rocketMQWorker = new CanalAdapterRocketMQWorker(canalClientConfig.getBootstrapServers(),
|
||||||
canalClientConfig.getBootstrapServers(),
|
|
||||||
topic.getTopic(),
|
topic.getTopic(),
|
||||||
group.getGroupId(),
|
group.getGroupId(),
|
||||||
canalOuterAdapterGroups);
|
canalOuterAdapterGroups);
|
||||||
canalMQWorker.put(topic.getTopic() + "-rocketmq-" + group.getGroupId(), rocketMQWorker);
|
canalMQWorker.put(topic.getTopic() + "-rocketmq-" + group.getGroupId(), rocketMQWorker);
|
||||||
rocketMQWorker.start();
|
rocketMQWorker.start();
|
||||||
} else if ("kafka".equalsIgnoreCase(topic.getMqMode())) {
|
} else if ("kafka".equalsIgnoreCase(topic.getMqMode())) {
|
||||||
CanalAdapterKafkaWorker canalKafkaWorker = new CanalAdapterKafkaWorker(
|
CanalAdapterKafkaWorker canalKafkaWorker = new CanalAdapterKafkaWorker(canalClientConfig.getBootstrapServers(),
|
||||||
canalClientConfig.getBootstrapServers(),
|
|
||||||
topic.getTopic(),
|
topic.getTopic(),
|
||||||
group.getGroupId(),
|
group.getGroupId(),
|
||||||
canalOuterAdapterGroups,canalClientConfig.getFlatMessage());
|
canalOuterAdapterGroups,
|
||||||
|
canalClientConfig.getFlatMessage());
|
||||||
canalMQWorker.put(topic.getTopic() + "-kafka-" + group.getGroupId(), canalKafkaWorker);
|
canalMQWorker.put(topic.getTopic() + "-kafka-" + group.getGroupId(), canalKafkaWorker);
|
||||||
canalKafkaWorker.start();
|
canalKafkaWorker.start();
|
||||||
}
|
}
|
||||||
logger.info("Start adapter for canal-client rocketmq topic: {} succeed",
|
logger.info("Start adapter for canal-client rocketmq topic: {} succeed", topic.getTopic() + "-"
|
||||||
topic.getTopic() + "-" + group.getGroupId());
|
+ group.getGroupId());
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -156,6 +163,7 @@ public class CanalAdapterLoader {
|
|||||||
for (AbstractCanalAdapterWorker tmp : canalMQWorker.values()) {
|
for (AbstractCanalAdapterWorker tmp : canalMQWorker.values()) {
|
||||||
final AbstractCanalAdapterWorker worker = tmp;
|
final AbstractCanalAdapterWorker worker = tmp;
|
||||||
stopMQWokerService.submit(new Runnable() {
|
stopMQWokerService.submit(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
worker.stop();
|
worker.stop();
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.loader;
|
package com.alibaba.otter.canal.client.adapter.loader;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.kafka.clients.consumer.CommitFailedException;
|
||||||
|
import org.apache.kafka.common.errors.WakeupException;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.adapter.CanalOuterAdapter;
|
import com.alibaba.otter.canal.client.adapter.CanalOuterAdapter;
|
||||||
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnector;
|
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnector;
|
||||||
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnectorProvider;
|
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnectorProvider;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import org.apache.kafka.clients.consumer.CommitFailedException;
|
|
||||||
import org.apache.kafka.common.errors.WakeupException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kafka对应的client适配器工作线程
|
* kafka对应的client适配器工作线程
|
||||||
|
|||||||
@@ -2,16 +2,19 @@ package com.alibaba.otter.canal.client;
|
|||||||
|
|
||||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket;
|
import com.alibaba.otter.canal.protocol.CanalPacket;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalPacket.Ack;
|
||||||
|
import com.alibaba.otter.canal.protocol.CanalPacket.Compression;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
|
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class CanalMessageDeserializer {
|
public class CanalMessageDeserializer {
|
||||||
private static Logger logger = LoggerFactory.getLogger(CanalMessageDeserializer.class);
|
|
||||||
|
|
||||||
public static Message deserializer(byte[] data) {
|
public static Message deserializer(byte[] data) {
|
||||||
|
return deserializer(data, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Message deserializer(byte[] data, boolean lazyParseEntry) {
|
||||||
try {
|
try {
|
||||||
if (data == null) {
|
if (data == null) {
|
||||||
return null;
|
return null;
|
||||||
@@ -19,24 +22,34 @@ public class CanalMessageDeserializer {
|
|||||||
CanalPacket.Packet p = CanalPacket.Packet.parseFrom(data);
|
CanalPacket.Packet p = CanalPacket.Packet.parseFrom(data);
|
||||||
switch (p.getType()) {
|
switch (p.getType()) {
|
||||||
case MESSAGES: {
|
case MESSAGES: {
|
||||||
// if (!p.getCompression().equals(CanalPacket.Compression.NONE)) {
|
if (!p.getCompression().equals(Compression.NONE)
|
||||||
// throw new CanalClientException("compression is not supported in this connector");
|
&& !p.getCompression().equals(Compression.COMPRESSIONCOMPATIBLEPROTO2)) {
|
||||||
// }
|
throw new CanalClientException("compression is not supported in this connector");
|
||||||
|
}
|
||||||
|
|
||||||
CanalPacket.Messages messages = CanalPacket.Messages.parseFrom(p.getBody());
|
CanalPacket.Messages messages = CanalPacket.Messages.parseFrom(p.getBody());
|
||||||
Message result = new Message(messages.getBatchId());
|
Message result = new Message(messages.getBatchId());
|
||||||
|
if (lazyParseEntry) {
|
||||||
|
// byteString
|
||||||
|
result.setRawEntries(messages.getMessagesList());
|
||||||
|
} else {
|
||||||
for (ByteString byteString : messages.getMessagesList()) {
|
for (ByteString byteString : messages.getMessagesList()) {
|
||||||
result.addEntry(CanalEntry.Entry.parseFrom(byteString));
|
result.addEntry(CanalEntry.Entry.parseFrom(byteString));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
default:
|
case ACK: {
|
||||||
break;
|
Ack ack = Ack.parseFrom(p.getBody());
|
||||||
|
throw new CanalClientException("something goes wrong with reason: " + ack.getErrorMessage());
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new CanalClientException("unexpected packet type: " + p.getType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("Error when deserializing byte[] to message ", e);
|
throw new CanalClientException("deserializer failed", e);
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,8 +218,7 @@ public class ClusterCanalConnector implements CanalConnector {
|
|||||||
return;
|
return;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.warn(String.format("something goes wrong when rollbacking data from server:%s",
|
logger.warn(String.format("something goes wrong when rollbacking data from server:%s",
|
||||||
currentConnector != null ? currentConnector.getAddress() : "null"),
|
currentConnector != null ? currentConnector.getAddress() : "null"), t);
|
||||||
t);
|
|
||||||
times++;
|
times++;
|
||||||
restart();
|
restart();
|
||||||
logger.info("restart the connector for next round retry.");
|
logger.info("restart the connector for next round retry.");
|
||||||
@@ -236,8 +235,7 @@ public class ClusterCanalConnector implements CanalConnector {
|
|||||||
return;
|
return;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.warn(String.format("something goes wrong when rollbacking data from server:%s",
|
logger.warn(String.format("something goes wrong when rollbacking data from server:%s",
|
||||||
currentConnector != null ? currentConnector.getAddress() : "null"),
|
currentConnector != null ? currentConnector.getAddress() : "null"), t);
|
||||||
t);
|
|
||||||
times++;
|
times++;
|
||||||
restart();
|
restart();
|
||||||
logger.info("restart the connector for next round retry.");
|
logger.info("restart the connector for next round retry.");
|
||||||
@@ -255,8 +253,7 @@ public class ClusterCanalConnector implements CanalConnector {
|
|||||||
return;
|
return;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.warn(String.format("something goes wrong when acking data from server:%s",
|
logger.warn(String.format("something goes wrong when acking data from server:%s",
|
||||||
currentConnector != null ? currentConnector.getAddress() : "null"),
|
currentConnector != null ? currentConnector.getAddress() : "null"), t);
|
||||||
t);
|
|
||||||
times++;
|
times++;
|
||||||
restart();
|
restart();
|
||||||
logger.info("restart the connector for next round retry.");
|
logger.info("restart the connector for next round retry.");
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.CanalConnector;
|
import com.alibaba.otter.canal.client.CanalConnector;
|
||||||
|
import com.alibaba.otter.canal.client.CanalMessageDeserializer;
|
||||||
import com.alibaba.otter.canal.client.impl.running.ClientRunningData;
|
import com.alibaba.otter.canal.client.impl.running.ClientRunningData;
|
||||||
import com.alibaba.otter.canal.client.impl.running.ClientRunningListener;
|
import com.alibaba.otter.canal.client.impl.running.ClientRunningListener;
|
||||||
import com.alibaba.otter.canal.client.impl.running.ClientRunningMonitor;
|
import com.alibaba.otter.canal.client.impl.running.ClientRunningMonitor;
|
||||||
import com.alibaba.otter.canal.common.utils.AddressUtils;
|
import com.alibaba.otter.canal.common.utils.AddressUtils;
|
||||||
import com.alibaba.otter.canal.common.utils.BooleanMutex;
|
import com.alibaba.otter.canal.common.utils.BooleanMutex;
|
||||||
import com.alibaba.otter.canal.common.zookeeper.ZkClientx;
|
import com.alibaba.otter.canal.common.zookeeper.ZkClientx;
|
||||||
import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
|
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Ack;
|
import com.alibaba.otter.canal.protocol.CanalPacket.Ack;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.ClientAck;
|
import com.alibaba.otter.canal.protocol.CanalPacket.ClientAck;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.ClientAuth;
|
import com.alibaba.otter.canal.protocol.CanalPacket.ClientAuth;
|
||||||
@@ -32,7 +32,6 @@ import com.alibaba.otter.canal.protocol.CanalPacket.ClientRollback;
|
|||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Compression;
|
import com.alibaba.otter.canal.protocol.CanalPacket.Compression;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Get;
|
import com.alibaba.otter.canal.protocol.CanalPacket.Get;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Handshake;
|
import com.alibaba.otter.canal.protocol.CanalPacket.Handshake;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Messages;
|
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Packet;
|
import com.alibaba.otter.canal.protocol.CanalPacket.Packet;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.PacketType;
|
import com.alibaba.otter.canal.protocol.CanalPacket.PacketType;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.Sub;
|
import com.alibaba.otter.canal.protocol.CanalPacket.Sub;
|
||||||
@@ -180,8 +179,8 @@ public class SimpleCanalConnector implements CanalConnector {
|
|||||||
|
|
||||||
Ack ackBody = Ack.parseFrom(ack.getBody());
|
Ack ackBody = Ack.parseFrom(ack.getBody());
|
||||||
if (ackBody.getErrorCode() > 0) {
|
if (ackBody.getErrorCode() > 0) {
|
||||||
throw new CanalClientException(
|
throw new CanalClientException("something goes wrong when doing authentication: "
|
||||||
"something goes wrong when doing authentication: " + ackBody.getErrorMessage());
|
+ ackBody.getErrorMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
connected = true;
|
connected = true;
|
||||||
@@ -320,34 +319,7 @@ public class SimpleCanalConnector implements CanalConnector {
|
|||||||
|
|
||||||
private Message receiveMessages() throws IOException {
|
private Message receiveMessages() throws IOException {
|
||||||
byte[] data = readNextPacket();
|
byte[] data = readNextPacket();
|
||||||
Packet p = Packet.parseFrom(data);
|
return CanalMessageDeserializer.deserializer(data, lazyParseEntry);
|
||||||
switch (p.getType()) {
|
|
||||||
case MESSAGES: {
|
|
||||||
if (!p.getCompression().equals(Compression.NONE)
|
|
||||||
&& !p.getCompression().equals(Compression.COMPRESSIONCOMPATIBLEPROTO2)) {
|
|
||||||
throw new CanalClientException("compression is not supported in this connector");
|
|
||||||
}
|
|
||||||
|
|
||||||
Messages messages = Messages.parseFrom(p.getBody());
|
|
||||||
Message result = new Message(messages.getBatchId());
|
|
||||||
if (lazyParseEntry) {
|
|
||||||
// byteString
|
|
||||||
result.setRawEntries(messages.getMessagesList());
|
|
||||||
} else {
|
|
||||||
for (ByteString byteString : messages.getMessagesList()) {
|
|
||||||
result.addEntry(Entry.parseFrom(byteString));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
case ACK: {
|
|
||||||
Ack ack = Ack.parseFrom(p.getBody());
|
|
||||||
throw new CanalClientException("something goes wrong with reason: " + ack.getErrorMessage());
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
throw new CanalClientException("unexpected packet type: " + p.getType());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ack(long batchId) throws CanalClientException {
|
public void ack(long batchId) throws CanalClientException {
|
||||||
@@ -361,8 +333,11 @@ public class SimpleCanalConnector implements CanalConnector {
|
|||||||
.setBatchId(batchId)
|
.setBatchId(batchId)
|
||||||
.build();
|
.build();
|
||||||
try {
|
try {
|
||||||
writeWithHeader(
|
writeWithHeader(Packet.newBuilder()
|
||||||
Packet.newBuilder().setType(PacketType.CLIENTACK).setBody(ca.toByteString()).build().toByteArray());
|
.setType(PacketType.CLIENTACK)
|
||||||
|
.setBody(ca.toByteString())
|
||||||
|
.build()
|
||||||
|
.toByteArray());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new CanalClientException(e);
|
throw new CanalClientException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.apache.kafka.common.TopicPartition;
|
|||||||
import org.apache.kafka.common.serialization.StringDeserializer;
|
import org.apache.kafka.common.serialization.StringDeserializer;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.otter.canal.client.CanalMessageDeserializer;
|
||||||
import com.alibaba.otter.canal.protocol.FlatMessage;
|
import com.alibaba.otter.canal.protocol.FlatMessage;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
|
|
||||||
@@ -33,8 +34,7 @@ public class KafkaCanalConnector {
|
|||||||
private volatile boolean running = false;
|
private volatile boolean running = false;
|
||||||
private boolean flatMessage;
|
private boolean flatMessage;
|
||||||
|
|
||||||
public KafkaCanalConnector(String servers, String topic, Integer partition, String groupId,
|
public KafkaCanalConnector(String servers, String topic, Integer partition, String groupId, boolean flatMessage){
|
||||||
boolean flatMessage){
|
|
||||||
this.topic = topic;
|
this.topic = topic;
|
||||||
this.partition = partition;
|
this.partition = partition;
|
||||||
this.flatMessage = flatMessage;
|
this.flatMessage = flatMessage;
|
||||||
@@ -50,7 +50,7 @@ public class KafkaCanalConnector {
|
|||||||
properties.put("max.poll.records", "100");
|
properties.put("max.poll.records", "100");
|
||||||
properties.put("key.deserializer", StringDeserializer.class.getName());
|
properties.put("key.deserializer", StringDeserializer.class.getName());
|
||||||
if (!flatMessage) {
|
if (!flatMessage) {
|
||||||
properties.put("value.deserializer", MessageDeserializer.class.getName());
|
properties.put("value.deserializer", CanalMessageDeserializer.class.getName());
|
||||||
} else {
|
} else {
|
||||||
properties.put("value.deserializer", StringDeserializer.class.getName());
|
properties.put("value.deserializer", StringDeserializer.class.getName());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ public class KafkaCanalConnectors {
|
|||||||
* @param groupId
|
* @param groupId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static KafkaCanalConnector newKafkaConnector(String servers, String topic, Integer partition,
|
public static KafkaCanalConnector newKafkaConnector(String servers, String topic, Integer partition, String groupId) {
|
||||||
String groupId) {
|
|
||||||
return new KafkaCanalConnector(servers, topic, partition, groupId, false);
|
return new KafkaCanalConnector(servers, topic, partition, groupId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,8 +43,8 @@ public class KafkaCanalConnectors {
|
|||||||
* @param flatMessage
|
* @param flatMessage
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static KafkaCanalConnector newKafkaConnector( String servers, String topic,
|
public static KafkaCanalConnector newKafkaConnector(String servers, String topic, Integer partition,
|
||||||
Integer partition, String groupId,boolean flatMessage) {
|
String groupId, boolean flatMessage) {
|
||||||
return new KafkaCanalConnector(servers, topic, partition, groupId, flatMessage);
|
return new KafkaCanalConnector(servers, topic, partition, groupId, flatMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
package com.alibaba.otter.canal.client.kafka;
|
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.CanalMessageDeserializer;
|
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.kafka.common.serialization.Deserializer;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kafka Message类的反序列化
|
|
||||||
*
|
|
||||||
* @author machengyuan @ 2018-6-12
|
|
||||||
* @version 1.0.0
|
|
||||||
*/
|
|
||||||
public class MessageDeserializer implements Deserializer<Message> {
|
|
||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(MessageDeserializer.class);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void configure(Map<String, ?> configs, boolean isKey) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Message deserialize(String topic1, byte[] data) {
|
|
||||||
return CanalMessageDeserializer.deserializer(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
// nothing to do
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -24,7 +24,6 @@ import com.alibaba.otter.canal.common.zookeeper.ZkClientx;
|
|||||||
import com.alibaba.otter.canal.common.zookeeper.ZookeeperPathUtils;
|
import com.alibaba.otter.canal.common.zookeeper.ZookeeperPathUtils;
|
||||||
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
|
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kafka client running状态信息
|
* kafka client running状态信息
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import java.util.concurrent.CountDownLatch;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
public class ConsumerBatchMessage<T> {
|
public class ConsumerBatchMessage<T> {
|
||||||
|
|
||||||
private final BlockingQueue<T> data;
|
private final BlockingQueue<T> data;
|
||||||
private CountDownLatch latch;
|
private CountDownLatch latch;
|
||||||
private boolean hasFailure = false;
|
private boolean hasFailure = false;
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
package com.alibaba.otter.canal.client.rocketmq;
|
package com.alibaba.otter.canal.client.rocketmq;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.CanalConnector;
|
|
||||||
import com.alibaba.otter.canal.client.CanalMessageDeserializer;
|
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
|
||||||
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
|
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
|
||||||
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
|
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
|
||||||
@@ -20,7 +17,13 @@ import org.apache.rocketmq.common.message.MessageExt;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.client.CanalConnector;
|
||||||
|
import com.alibaba.otter.canal.client.CanalMessageDeserializer;
|
||||||
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
|
import com.alibaba.otter.canal.protocol.exception.CanalClientException;
|
||||||
|
|
||||||
public class RocketMQCanalConnector implements CanalConnector {
|
public class RocketMQCanalConnector implements CanalConnector {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(RocketMQCanalConnector.class);
|
private static final Logger logger = LoggerFactory.getLogger(RocketMQCanalConnector.class);
|
||||||
|
|
||||||
private String nameServer;
|
private String nameServer;
|
||||||
@@ -69,9 +72,9 @@ public class RocketMQCanalConnector implements CanalConnector {
|
|||||||
}
|
}
|
||||||
rocketMQConsumer.subscribe(topic, "*");
|
rocketMQConsumer.subscribe(topic, "*");
|
||||||
rocketMQConsumer.registerMessageListener(new MessageListenerOrderly() {
|
rocketMQConsumer.registerMessageListener(new MessageListenerOrderly() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> messageExts,
|
public ConsumeOrderlyStatus consumeMessage(List<MessageExt> messageExts, ConsumeOrderlyContext context) {
|
||||||
ConsumeOrderlyContext context) {
|
|
||||||
context.setAutoCommit(true);
|
context.setAutoCommit(true);
|
||||||
boolean isSuccess = process(messageExts);
|
boolean isSuccess = process(messageExts);
|
||||||
if (isSuccess) {
|
if (isSuccess) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package com.alibaba.otter.canal.client.rocketmq;
|
|||||||
* RocketMQ connector provider.
|
* RocketMQ connector provider.
|
||||||
*/
|
*/
|
||||||
public class RocketMQCanalConnectorProvider {
|
public class RocketMQCanalConnectorProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create RocketMQ connector
|
* Create RocketMQ connector
|
||||||
*
|
*
|
||||||
@@ -12,8 +13,7 @@ public class RocketMQCanalConnectorProvider {
|
|||||||
* @param groupId
|
* @param groupId
|
||||||
* @return {@link RocketMQCanalConnector}
|
* @return {@link RocketMQCanalConnector}
|
||||||
*/
|
*/
|
||||||
public static RocketMQCanalConnector newRocketMQConnector(String nameServers, String topic,
|
public static RocketMQCanalConnector newRocketMQConnector(String nameServers, String topic, String groupId) {
|
||||||
String groupId) {
|
|
||||||
return new RocketMQCanalConnector(nameServers, topic, groupId);
|
return new RocketMQCanalConnector(nameServers, topic, groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package com.alibaba.otter.canal.client.rocketmq;
|
package com.alibaba.otter.canal.client.rocketmq;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.rocketmq.common.message.MessageExt;
|
import org.apache.rocketmq.common.message.MessageExt;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RocketMQ message listener
|
* RocketMQ message listener
|
||||||
*/
|
*/
|
||||||
public interface RocketMQCanalListener {
|
public interface RocketMQCanalListener {
|
||||||
|
|
||||||
boolean onReceive(List<MessageExt> messageExts);
|
boolean onReceive(List<MessageExt> messageExts);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,8 +41,7 @@ public class CanalKafkaClientExample {
|
|||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
final CanalKafkaClientExample kafkaCanalClientExample = new CanalKafkaClientExample(
|
final CanalKafkaClientExample kafkaCanalClientExample = new CanalKafkaClientExample(AbstractKafkaTest.zkServers,
|
||||||
AbstractKafkaTest.zkServers,
|
|
||||||
AbstractKafkaTest.servers,
|
AbstractKafkaTest.servers,
|
||||||
AbstractKafkaTest.topic,
|
AbstractKafkaTest.topic,
|
||||||
AbstractKafkaTest.partition,
|
AbstractKafkaTest.partition,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.alibaba.otter.canal.client.running.rocketmq;
|
package com.alibaba.otter.canal.client.running.rocketmq;
|
||||||
|
|
||||||
public class AbstractRocektMQTest {
|
public class AbstractRocektMQTest {
|
||||||
|
|
||||||
public static String topic = "example";
|
public static String topic = "example";
|
||||||
public static String groupId = "group";
|
public static String groupId = "group";
|
||||||
public static String nameServers = "localhost:9876";
|
public static String nameServers = "localhost:9876";
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
package com.alibaba.otter.canal.client.running.rocketmq;
|
package com.alibaba.otter.canal.client.running.rocketmq;
|
||||||
|
|
||||||
|
import org.apache.kafka.common.errors.WakeupException;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnector;
|
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnector;
|
||||||
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnectorProvider;
|
import com.alibaba.otter.canal.client.rocketmq.RocketMQCanalConnectorProvider;
|
||||||
import com.alibaba.otter.canal.client.running.kafka.AbstractKafkaTest;
|
import com.alibaba.otter.canal.client.running.kafka.AbstractKafkaTest;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
import org.apache.kafka.common.errors.WakeupException;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kafka client example
|
* Kafka client example
|
||||||
@@ -32,17 +33,15 @@ public class CanalRocketMQClientExample extends AbstractRocektMQTest {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public CanalRocketMQClientExample(String nameServers, String topic,
|
public CanalRocketMQClientExample(String nameServers, String topic, String groupId){
|
||||||
String groupId) {
|
connector = RocketMQCanalConnectorProvider.newRocketMQConnector(nameServers, topic, groupId);
|
||||||
connector = RocketMQCanalConnectorProvider.newRocketMQConnector(nameServers,
|
|
||||||
topic,
|
|
||||||
groupId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
try {
|
try {
|
||||||
final CanalRocketMQClientExample rocketMQClientExample = new CanalRocketMQClientExample(nameServers,
|
final CanalRocketMQClientExample rocketMQClientExample = new CanalRocketMQClientExample(nameServers,
|
||||||
topic, groupId);
|
topic,
|
||||||
|
groupId);
|
||||||
logger.info("## Start the rocketmq consumer: {}-{}", AbstractKafkaTest.topic, AbstractKafkaTest.groupId);
|
logger.info("## Start the rocketmq consumer: {}-{}", AbstractKafkaTest.topic, AbstractKafkaTest.groupId);
|
||||||
rocketMQClientExample.start();
|
rocketMQClientExample.start();
|
||||||
logger.info("## The canal rocketmq consumer is running now ......");
|
logger.info("## The canal rocketmq consumer is running now ......");
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ canal.zkServers=
|
|||||||
canal.zookeeper.flush.period = 1000
|
canal.zookeeper.flush.period = 1000
|
||||||
canal.withoutNetty = false
|
canal.withoutNetty = false
|
||||||
# tcp, kafka, RocketMQ
|
# tcp, kafka, RocketMQ
|
||||||
canal.serverMode = rocketmq
|
canal.serverMode = tcp
|
||||||
# flush meta cursor/parse position to file
|
# flush meta cursor/parse position to file
|
||||||
canal.file.data.dir = ${canal.conf.dir}
|
canal.file.data.dir = ${canal.conf.dir}
|
||||||
canal.file.flush.period = 1000
|
canal.file.flush.period = 1000
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import com.alibaba.otter.canal.common.utils.CanalToStringStyle;
|
|||||||
*/
|
*/
|
||||||
public class ClientIdentity implements Serializable {
|
public class ClientIdentity implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = -8262100681930834834L;
|
||||||
private String destination;
|
private String destination;
|
||||||
private short clientId;
|
private short clientId;
|
||||||
private String filter;
|
private String filter;
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package com.alibaba.otter.canal.common;
|
package com.alibaba.otter.canal.common;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.kafka.common.errors.SerializationException;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket;
|
import com.alibaba.otter.canal.protocol.CanalPacket;
|
||||||
import com.alibaba.otter.canal.protocol.CanalPacket.PacketType;
|
import com.alibaba.otter.canal.protocol.CanalPacket.PacketType;
|
||||||
@@ -7,11 +12,10 @@ import com.alibaba.otter.canal.protocol.Message;
|
|||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.CodedOutputStream;
|
import com.google.protobuf.CodedOutputStream;
|
||||||
import com.google.protobuf.WireFormat;
|
import com.google.protobuf.WireFormat;
|
||||||
import java.util.List;
|
|
||||||
import org.apache.kafka.common.errors.SerializationException;
|
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
|
|
||||||
public class CanalMessageSerializer {
|
public class CanalMessageSerializer {
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
public static byte[] serializer(Message data) {
|
public static byte[] serializer(Message data) {
|
||||||
try {
|
try {
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
@@ -31,11 +35,9 @@ public class CanalMessageSerializer {
|
|||||||
messageSize += 1 * rowEntries.size();
|
messageSize += 1 * rowEntries.size();
|
||||||
// packet size
|
// packet size
|
||||||
int size = 0;
|
int size = 0;
|
||||||
size += CodedOutputStream.computeEnumSize(3,
|
size += CodedOutputStream.computeEnumSize(3, PacketType.MESSAGES.getNumber());
|
||||||
PacketType.MESSAGES.getNumber());
|
|
||||||
size += CodedOutputStream.computeTagSize(5)
|
size += CodedOutputStream.computeTagSize(5)
|
||||||
+ CodedOutputStream.computeRawVarint32Size(messageSize)
|
+ CodedOutputStream.computeRawVarint32Size(messageSize) + messageSize;
|
||||||
+ messageSize;
|
|
||||||
// build data
|
// build data
|
||||||
byte[] body = new byte[size];
|
byte[] body = new byte[size];
|
||||||
CodedOutputStream output = CodedOutputStream.newInstance(body);
|
CodedOutputStream output = CodedOutputStream.newInstance(body);
|
||||||
|
|||||||
@@ -74,7 +74,6 @@ public class MQProperties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String getServers() {
|
public String getServers() {
|
||||||
return servers;
|
return servers;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
package com.alibaba.otter.canal.kafka;
|
package com.alibaba.otter.canal.kafka;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.otter.canal.common.MQProperties;
|
|
||||||
import com.alibaba.otter.canal.protocol.FlatMessage;
|
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
|
||||||
import com.alibaba.otter.canal.spi.CanalMQProducer;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||||
import org.apache.kafka.clients.producer.Producer;
|
import org.apache.kafka.clients.producer.Producer;
|
||||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||||
@@ -14,6 +10,13 @@ import org.apache.kafka.common.serialization.StringSerializer;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson.JSON;
|
||||||
|
import com.alibaba.otter.canal.common.MQProperties;
|
||||||
|
import com.alibaba.otter.canal.protocol.FlatMessage;
|
||||||
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
|
import com.alibaba.otter.canal.spi.CanalMQProducer;
|
||||||
|
;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kafka producer 主操作类
|
* kafka producer 主操作类
|
||||||
*
|
*
|
||||||
@@ -91,8 +94,10 @@ public class CanalKafkaProducer implements CanalMQProducer {
|
|||||||
if (flatMessages != null) {
|
if (flatMessages != null) {
|
||||||
for (FlatMessage flatMessage : flatMessages) {
|
for (FlatMessage flatMessage : flatMessages) {
|
||||||
if (canalDestination.getPartition() != null) {
|
if (canalDestination.getPartition() != null) {
|
||||||
ProducerRecord<String, String> record = new ProducerRecord<String, String>(canalDestination
|
ProducerRecord<String, String> record = new ProducerRecord<String, String>(canalDestination.getTopic(),
|
||||||
.getTopic(), canalDestination.getPartition(), null, JSON.toJSONString(flatMessage));
|
canalDestination.getPartition(),
|
||||||
|
null,
|
||||||
|
JSON.toJSONString(flatMessage));
|
||||||
producer2.send(record);
|
producer2.send(record);
|
||||||
} else {
|
} else {
|
||||||
if (canalDestination.getPartitionHash() != null
|
if (canalDestination.getPartitionHash() != null
|
||||||
@@ -104,8 +109,7 @@ public class CanalKafkaProducer implements CanalMQProducer {
|
|||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
FlatMessage flatMessagePart = partitionFlatMessage[i];
|
FlatMessage flatMessagePart = partitionFlatMessage[i];
|
||||||
if (flatMessagePart != null) {
|
if (flatMessagePart != null) {
|
||||||
ProducerRecord<String, String> record = new ProducerRecord<String, String>(
|
ProducerRecord<String, String> record = new ProducerRecord<String, String>(canalDestination.getTopic(),
|
||||||
canalDestination.getTopic(),
|
|
||||||
i,
|
i,
|
||||||
null,
|
null,
|
||||||
JSON.toJSONString(flatMessagePart));
|
JSON.toJSONString(flatMessagePart));
|
||||||
@@ -113,8 +117,7 @@ public class CanalKafkaProducer implements CanalMQProducer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ProducerRecord<String, String> record = new ProducerRecord<String, String>(
|
ProducerRecord<String, String> record = new ProducerRecord<String, String>(canalDestination.getTopic(),
|
||||||
canalDestination.getTopic(),
|
|
||||||
0,
|
0,
|
||||||
null,
|
null,
|
||||||
JSON.toJSONString(flatMessage));
|
JSON.toJSONString(flatMessage));
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.alibaba.otter.canal.kafka;
|
package com.alibaba.otter.canal.kafka;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.kafka.common.serialization.Serializer;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.common.CanalMessageSerializer;
|
import com.alibaba.otter.canal.common.CanalMessageSerializer;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
import java.util.Map;
|
|
||||||
import org.apache.kafka.common.serialization.Serializer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Kafka Message类的序列化
|
* Kafka Message类的序列化
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.slf4j.Logger;
|
|||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class CanalRocketMQProducer implements CanalMQProducer {
|
public class CanalRocketMQProducer implements CanalMQProducer {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(CanalRocketMQProducer.class);
|
private static final Logger logger = LoggerFactory.getLogger(CanalRocketMQProducer.class);
|
||||||
|
|
||||||
private DefaultMQProducer defaultMQProducer;
|
private DefaultMQProducer defaultMQProducer;
|
||||||
@@ -40,6 +41,7 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
|||||||
try {
|
try {
|
||||||
Message message = new Message(destination.getTopic(), CanalMessageSerializer.serializer(data));
|
Message message = new Message(destination.getTopic(), CanalMessageSerializer.serializer(data));
|
||||||
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
||||||
int partition = 0;
|
int partition = 0;
|
||||||
|
|||||||
@@ -1,22 +1,25 @@
|
|||||||
package com.alibaba.otter.canal.server;
|
package com.alibaba.otter.canal.server;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.yaml.snakeyaml.Yaml;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.common.MQProperties;
|
import com.alibaba.otter.canal.common.MQProperties;
|
||||||
import com.alibaba.otter.canal.kafka.CanalKafkaProducer;
|
import com.alibaba.otter.canal.kafka.CanalKafkaProducer;
|
||||||
import com.alibaba.otter.canal.protocol.ClientIdentity;
|
import com.alibaba.otter.canal.protocol.ClientIdentity;
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
import com.alibaba.otter.canal.server.embedded.CanalServerWithEmbedded;
|
import com.alibaba.otter.canal.server.embedded.CanalServerWithEmbedded;
|
||||||
import com.alibaba.otter.canal.spi.CanalMQProducer;
|
import com.alibaba.otter.canal.spi.CanalMQProducer;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
public class CanalMQStarter {
|
public class CanalMQStarter {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(CanalMQStarter.class);
|
private static final Logger logger = LoggerFactory.getLogger(CanalMQStarter.class);
|
||||||
|
|
||||||
private static final String CLASSPATH_URL_PREFIX = "classpath:";
|
private static final String CLASSPATH_URL_PREFIX = "classpath:";
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class SessionHandler extends SimpleChannelHandler {
|
|||||||
this.embeddedServer = embeddedServer;
|
this.embeddedServer = embeddedServer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings({ "deprecation", "deprecation" })
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
||||||
logger.info("message receives in session handler...");
|
logger.info("message receives in session handler...");
|
||||||
long start = System.nanoTime();
|
long start = System.nanoTime();
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.alibaba.otter.canal.spi;
|
package com.alibaba.otter.canal.spi;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.common.MQProperties;
|
|
||||||
import com.alibaba.otter.canal.kafka.CanalKafkaProducer;
|
|
||||||
import com.alibaba.otter.canal.protocol.Message;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.common.MQProperties;
|
||||||
|
import com.alibaba.otter.canal.protocol.Message;
|
||||||
|
|
||||||
public interface CanalMQProducer {
|
public interface CanalMQProducer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Init producer.
|
* Init producer.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user