mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
adapter代码整理优化
This commit is contained in:
@@ -84,7 +84,7 @@ public class YmlConfigBinder {
|
|||||||
try {
|
try {
|
||||||
byte[] contentBytes;
|
byte[] contentBytes;
|
||||||
if (charset == null) {
|
if (charset == null) {
|
||||||
contentBytes = content.getBytes();
|
contentBytes = content.getBytes("UTF-8");
|
||||||
} else {
|
} else {
|
||||||
contentBytes = content.getBytes(charset);
|
contentBytes = content.getBytes(charset);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class RelaxedConversionService implements ConversionService {
|
|||||||
return new RelaxedConversionService.StringToEnumIgnoringCaseConverterFactory.StringToEnum(enumType);
|
return new RelaxedConversionService.StringToEnumIgnoringCaseConverterFactory.StringToEnum(enumType);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StringToEnum<T extends Enum> implements Converter<String, T> {
|
private static class StringToEnum<T extends Enum> implements Converter<String, T> {
|
||||||
|
|
||||||
private final Class<T> enumType;
|
private final Class<T> enumType;
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ public abstract class YamlProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
private boolean process(Map<String, Object> map, MatchCallback callback) {
|
||||||
|
@SuppressWarnings("serial")
|
||||||
Properties properties = new Properties() {
|
Properties properties = new Properties() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ 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.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
@@ -27,7 +28,8 @@ import org.slf4j.LoggerFactory;
|
|||||||
*/
|
*/
|
||||||
public class ExtensionLoader<T> {
|
public class ExtensionLoader<T> {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ExtensionLoader.class);
|
private static final Logger logger = LoggerFactory
|
||||||
|
.getLogger(ExtensionLoader.class);
|
||||||
|
|
||||||
private static final String SERVICES_DIRECTORY = "META-INF/services/";
|
private static final String SERVICES_DIRECTORY = "META-INF/services/";
|
||||||
|
|
||||||
@@ -35,7 +37,8 @@ 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.compile("\\s*[,]+\\s*");
|
private static final Pattern NAME_SEPARATOR = Pattern
|
||||||
|
.compile("\\s*[,]+\\s*");
|
||||||
|
|
||||||
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
@@ -171,7 +174,8 @@ 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(), t);
|
+ ") could not be instantiated: " + t.getMessage(),
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,7 +195,8 @@ 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(), t);
|
+ ") could not be instantiated: " + t.getMessage(),
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +238,11 @@ public class ExtensionLoader<T> {
|
|||||||
// button.
|
// button.
|
||||||
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
|
jarPath = jarPath.replaceAll("/classes/.*", "/classes/");
|
||||||
}
|
}
|
||||||
return Paths.get(jarPath).getParent().toString(); // Paths - from java 8
|
Path path = Paths.get(jarPath).getParent(); // Paths - from java 8
|
||||||
|
if (path != null) {
|
||||||
|
return path.toString();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, Class<?>> loadExtensionClasses() {
|
private Map<String, Class<?>> loadExtensionClasses() {
|
||||||
@@ -330,12 +339,10 @@ public class ExtensionLoader<T> {
|
|||||||
// Class.forName(line, true,
|
// Class.forName(line, true,
|
||||||
// classLoader);
|
// classLoader);
|
||||||
if (!type.isAssignableFrom(clazz)) {
|
if (!type.isAssignableFrom(clazz)) {
|
||||||
throw new IllegalStateException("Error when load extension class(interface: "
|
throw new IllegalStateException(
|
||||||
+ type
|
"Error when load extension class(interface: " + type
|
||||||
+ ", class line: "
|
+ ", class line: " + clazz.getName()
|
||||||
+ clazz.getName()
|
+ "), class " + clazz.getName()
|
||||||
+ "), class "
|
|
||||||
+ clazz.getName()
|
|
||||||
+ "is not subtype of interface.");
|
+ "is not subtype of interface.");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@@ -353,9 +360,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("Duplicate extension "
|
throw new IllegalStateException(
|
||||||
+ type.getName()
|
"Duplicate extension " + type.getName() + " name "
|
||||||
+ " name " + n + " on "
|
+ n + " on "
|
||||||
+ c.getName() + " and "
|
+ c.getName() + " and "
|
||||||
+ clazz.getName());
|
+ clazz.getName());
|
||||||
}
|
}
|
||||||
@@ -365,12 +372,9 @@ public class ExtensionLoader<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: "
|
IllegalStateException e = new IllegalStateException(
|
||||||
+ type
|
"Failed to load extension class(interface: " + type + ", class line: "
|
||||||
+ ", class line: "
|
+ line + ") in " + url
|
||||||
+ line
|
|
||||||
+ ") in "
|
|
||||||
+ url
|
|
||||||
+ ", cause: "
|
+ ", cause: "
|
||||||
+ t.getMessage(),
|
+ t.getMessage(),
|
||||||
t);
|
t);
|
||||||
@@ -385,13 +389,15 @@ 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, t);
|
+ ") in " + url,
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
} // end of while urls
|
} // end of while urls
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
logger.error("Exception when load extension class(interface: " + type + ", description file: " + fileName
|
logger.error(
|
||||||
+ ").", t);
|
"Exception when load extension class(interface: " + type + ", description file: " + fileName + ").",
|
||||||
|
t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -155,9 +155,11 @@ public class JdbcTypeUtil {
|
|||||||
} else {
|
} else {
|
||||||
res = null;
|
res = null;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case Types.CLOB:
|
case Types.CLOB:
|
||||||
default:
|
default:
|
||||||
res = value;
|
res = value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -12,10 +12,10 @@ import java.util.Date;
|
|||||||
public class Result implements Serializable {
|
public class Result implements Serializable {
|
||||||
|
|
||||||
private static final long serialVersionUID = -3276409502352405716L;
|
private static final long serialVersionUID = -3276409502352405716L;
|
||||||
public Integer code = 20000;
|
private Integer code = 20000;
|
||||||
public Object data;
|
private Object data;
|
||||||
public String message;
|
private String message;
|
||||||
public Date sysTime;
|
private Date sysTime;
|
||||||
|
|
||||||
public static Result createSuccess(String message) {
|
public static Result createSuccess(String message) {
|
||||||
Result result = new Result();
|
Result result = new Result();
|
||||||
|
|||||||
@@ -2,7 +2,10 @@ package com.alibaba.otter.canal.client.adapter.support;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.sql.*;
|
import java.sql.Connection;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
import java.time.*;
|
import java.time.*;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@@ -29,38 +32,16 @@ public class Util {
|
|||||||
/**
|
/**
|
||||||
* 通过DS执行sql
|
* 通过DS执行sql
|
||||||
*/
|
*/
|
||||||
public static Object sqlRS(DataSource ds, String sql, Function<ResultSet, Object> fun) throws SQLException {
|
public static Object sqlRS(DataSource ds, String sql, Function<ResultSet, Object> fun) {
|
||||||
Connection conn = null;
|
try (Connection conn = ds.getConnection();
|
||||||
Statement stmt = null;
|
Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);) {
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
conn = ds.getConnection();
|
|
||||||
stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
|
||||||
stmt.setFetchSize(Integer.MIN_VALUE);
|
stmt.setFetchSize(Integer.MIN_VALUE);
|
||||||
rs = stmt.executeQuery(sql);
|
try (ResultSet rs = stmt.executeQuery(sql);) {
|
||||||
return fun.apply(rs);
|
return fun.apply(rs);
|
||||||
} finally {
|
|
||||||
if (rs != null) {
|
|
||||||
try {
|
|
||||||
rs.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stmt != null) {
|
|
||||||
try {
|
|
||||||
stmt.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (conn != null) {
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("sqlRs has error, sql: {} ", sql);
|
||||||
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,29 +53,10 @@ public class Util {
|
|||||||
* @param consumer 回调方法
|
* @param consumer 回调方法
|
||||||
*/
|
*/
|
||||||
public static void sqlRS(Connection conn, String sql, Consumer<ResultSet> consumer) {
|
public static void sqlRS(Connection conn, String sql, Consumer<ResultSet> consumer) {
|
||||||
Statement stmt = null;
|
try (Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery(sql)) {
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
stmt = conn.createStatement();
|
|
||||||
rs = stmt.executeQuery(sql);
|
|
||||||
consumer.accept(rs);
|
consumer.accept(rs);
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
logger.error(e.getMessage(), e);
|
logger.error(e.getMessage(), e);
|
||||||
} finally {
|
|
||||||
if (rs != null) {
|
|
||||||
try {
|
|
||||||
rs.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stmt != null) {
|
|
||||||
try {
|
|
||||||
stmt.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error(e.getMessage(), e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,7 +106,7 @@ public class Util {
|
|||||||
return column;
|
return column;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String timeZone; // 当前时区
|
public final static String timeZone; // 当前时区
|
||||||
private static DateTimeZone dateTimeZone;
|
private static DateTimeZone dateTimeZone;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
@@ -265,7 +227,7 @@ public class Util {
|
|||||||
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
|
LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
|
||||||
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
logger.error(e.getMessage(), e);
|
logger.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ public class ESAdapter implements OuterAdapter {
|
|||||||
|
|
||||||
esConfigMonitor = new ESConfigMonitor();
|
esConfigMonitor = new ESConfigMonitor();
|
||||||
esConfigMonitor.init(this, envProperties);
|
esConfigMonitor.init(this, envProperties);
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ES 映射配置
|
* ES 映射配置
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -278,12 +278,13 @@ public class SchemaItem {
|
|||||||
if (relationSelectFieldItems == null) {
|
if (relationSelectFieldItems == null) {
|
||||||
synchronized (SchemaItem.class) {
|
synchronized (SchemaItem.class) {
|
||||||
if (relationSelectFieldItems == null) {
|
if (relationSelectFieldItems == null) {
|
||||||
relationSelectFieldItems = new ArrayList<>();
|
List<FieldItem> relationSelectFieldItemsTmp = new ArrayList<>();
|
||||||
for (FieldItem fieldItem : schemaItem.getSelectFields().values()) {
|
for (FieldItem fieldItem : schemaItem.getSelectFields().values()) {
|
||||||
if (fieldItem.getOwners().contains(getAlias())) {
|
if (fieldItem.getOwners().contains(getAlias())) {
|
||||||
relationSelectFieldItems.add(fieldItem);
|
relationSelectFieldItemsTmp.add(fieldItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
relationSelectFieldItems = relationSelectFieldItemsTmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,16 +7,15 @@ import java.util.Properties;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.adapter.config.YmlConfigBinder;
|
|
||||||
import org.apache.commons.io.filefilter.FileFilterUtils;
|
import org.apache.commons.io.filefilter.FileFilterUtils;
|
||||||
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
|
import org.apache.commons.io.monitor.FileAlterationListenerAdaptor;
|
||||||
import org.apache.commons.io.monitor.FileAlterationMonitor;
|
import org.apache.commons.io.monitor.FileAlterationMonitor;
|
||||||
import org.apache.commons.io.monitor.FileAlterationObserver;
|
import org.apache.commons.io.monitor.FileAlterationObserver;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.yaml.snakeyaml.Yaml;
|
|
||||||
|
|
||||||
import com.alibaba.druid.pool.DruidDataSource;
|
import com.alibaba.druid.pool.DruidDataSource;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.config.YmlConfigBinder;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.ESAdapter;
|
import com.alibaba.otter.canal.client.adapter.es.ESAdapter;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.config.ESSyncConfig;
|
import com.alibaba.otter.canal.client.adapter.es.config.ESSyncConfig;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem;
|
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem;
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.es.service;
|
package com.alibaba.otter.canal.client.adapter.es.service;
|
||||||
|
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.SynchronousQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@@ -29,10 +35,10 @@ import com.alibaba.druid.pool.DruidDataSource;
|
|||||||
import com.alibaba.otter.canal.client.adapter.es.config.ESSyncConfig;
|
import com.alibaba.otter.canal.client.adapter.es.config.ESSyncConfig;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.config.ESSyncConfig.ESMapping;
|
import com.alibaba.otter.canal.client.adapter.es.config.ESSyncConfig.ESMapping;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem.FieldItem;
|
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem.FieldItem;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.support.ESSyncUtil;
|
|
||||||
import com.alibaba.otter.canal.client.adapter.es.support.ESTemplate;
|
import com.alibaba.otter.canal.client.adapter.es.support.ESTemplate;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.DatasourceConfig;
|
import com.alibaba.otter.canal.client.adapter.support.DatasourceConfig;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.EtlResult;
|
import com.alibaba.otter.canal.client.adapter.support.EtlResult;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.Util;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -99,7 +105,7 @@ public class ESEtlService {
|
|||||||
|
|
||||||
// 获取总数
|
// 获取总数
|
||||||
String countSql = "SELECT COUNT(1) FROM ( " + sql + ") _CNT ";
|
String countSql = "SELECT COUNT(1) FROM ( " + sql + ") _CNT ";
|
||||||
long cnt = (Long) ESSyncUtil.sqlRS(dataSource, countSql, rs -> {
|
long cnt = (Long) Util.sqlRS(dataSource, countSql, rs -> {
|
||||||
Long count = null;
|
Long count = null;
|
||||||
try {
|
try {
|
||||||
if (rs.next()) {
|
if (rs.next()) {
|
||||||
@@ -115,7 +121,20 @@ public class ESEtlService {
|
|||||||
if (cnt >= 10000) {
|
if (cnt >= 10000) {
|
||||||
int threadCount = 3; // 从配置读取默认为3
|
int threadCount = 3; // 从配置读取默认为3
|
||||||
long perThreadCnt = cnt / threadCount;
|
long perThreadCnt = cnt / threadCount;
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
ExecutorService executor = new ThreadPoolExecutor(threadCount,
|
||||||
|
threadCount,
|
||||||
|
5000L,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
new SynchronousQueue<>(),
|
||||||
|
(r, exe) -> {
|
||||||
|
if (!exe.isShutdown()) {
|
||||||
|
try {
|
||||||
|
exe.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
List<Future<Boolean>> futures = new ArrayList<>(threadCount);
|
List<Future<Boolean>> futures = new ArrayList<>(threadCount);
|
||||||
for (int i = 0; i < threadCount; i++) {
|
for (int i = 0; i < threadCount; i++) {
|
||||||
long offset = i * perThreadCnt;
|
long offset = i * perThreadCnt;
|
||||||
@@ -175,7 +194,7 @@ public class ESEtlService {
|
|||||||
private boolean executeSqlImport(DataSource ds, String sql, ESMapping mapping, AtomicLong impCount,
|
private boolean executeSqlImport(DataSource ds, String sql, ESMapping mapping, AtomicLong impCount,
|
||||||
List<String> errMsg) {
|
List<String> errMsg) {
|
||||||
try {
|
try {
|
||||||
ESSyncUtil.sqlRS(ds, sql, rs -> {
|
Util.sqlRS(ds, sql, rs -> {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try {
|
try {
|
||||||
BulkRequestBuilder bulkRequestBuilder = transportClient.prepareBulk();
|
BulkRequestBuilder bulkRequestBuilder = transportClient.prepareBulk();
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import java.util.Map;
|
|||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.Util;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -464,7 +465,7 @@ public class ESSyncService {
|
|||||||
mapping.get_index(),
|
mapping.get_index(),
|
||||||
sql.replace("\n", " "));
|
sql.replace("\n", " "));
|
||||||
}
|
}
|
||||||
ESSyncUtil.sqlRS(ds, sql, rs -> {
|
Util.sqlRS(ds, sql, rs -> {
|
||||||
try {
|
try {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
||||||
@@ -500,7 +501,7 @@ public class ESSyncService {
|
|||||||
mapping.get_index(),
|
mapping.get_index(),
|
||||||
sql.replace("\n", " "));
|
sql.replace("\n", " "));
|
||||||
}
|
}
|
||||||
ESSyncUtil.sqlRS(ds, sql, rs -> {
|
Util.sqlRS(ds, sql, rs -> {
|
||||||
try {
|
try {
|
||||||
Map<String, Object> esFieldData = null;
|
Map<String, Object> esFieldData = null;
|
||||||
if (mapping.getPk() != null) {
|
if (mapping.getPk() != null) {
|
||||||
@@ -601,7 +602,7 @@ public class ESSyncService {
|
|||||||
mapping.get_index(),
|
mapping.get_index(),
|
||||||
sql.toString().replace("\n", " "));
|
sql.toString().replace("\n", " "));
|
||||||
}
|
}
|
||||||
ESSyncUtil.sqlRS(ds, sql.toString(), rs -> {
|
Util.sqlRS(ds, sql.toString(), rs -> {
|
||||||
try {
|
try {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
||||||
@@ -693,7 +694,7 @@ public class ESSyncService {
|
|||||||
mapping.get_index(),
|
mapping.get_index(),
|
||||||
sql.toString().replace("\n", " "));
|
sql.toString().replace("\n", " "));
|
||||||
}
|
}
|
||||||
ESSyncUtil.sqlRS(ds, sql.toString(), rs -> {
|
Util.sqlRS(ds, sql.toString(), rs -> {
|
||||||
try {
|
try {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
||||||
@@ -812,7 +813,7 @@ public class ESSyncService {
|
|||||||
mapping.get_index(),
|
mapping.get_index(),
|
||||||
sql.replace("\n", " "));
|
sql.replace("\n", " "));
|
||||||
}
|
}
|
||||||
ESSyncUtil.sqlRS(ds, sql, rs -> {
|
Util.sqlRS(ds, sql, rs -> {
|
||||||
try {
|
try {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
Map<String, Object> esFieldData = new LinkedHashMap<>();
|
||||||
|
|||||||
@@ -3,12 +3,9 @@ package com.alibaba.otter.canal.client.adapter.es.support;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.*;
|
import java.sql.Blob;
|
||||||
|
import java.sql.SQLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
@@ -234,8 +231,11 @@ public class ESSyncUtil {
|
|||||||
private static byte[] blobToBytes(Blob blob) {
|
private static byte[] blobToBytes(Blob blob) {
|
||||||
try (InputStream is = blob.getBinaryStream()) {
|
try (InputStream is = blob.getBinaryStream()) {
|
||||||
byte[] b = new byte[(int) blob.length()];
|
byte[] b = new byte[(int) blob.length()];
|
||||||
is.read(b);
|
if (is.read(b) != -1) {
|
||||||
return b;
|
return b;
|
||||||
|
} else {
|
||||||
|
return new byte[0];
|
||||||
|
}
|
||||||
} catch (IOException | SQLException e) {
|
} catch (IOException | SQLException e) {
|
||||||
logger.error(e.getMessage());
|
logger.error(e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
@@ -297,46 +297,4 @@ public class ESSyncUtil {
|
|||||||
sql.append(owner).append(".").append(columnName).append("=").append(value).append(" AND ");
|
sql.append(owner).append(".").append(columnName).append("=").append(value).append(" AND ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 执行查询sql
|
|
||||||
*/
|
|
||||||
public static Object sqlRS(DataSource ds, String sql, Function<ResultSet, Object> fun) {
|
|
||||||
Connection conn = null;
|
|
||||||
Statement smt = null;
|
|
||||||
ResultSet rs = null;
|
|
||||||
try {
|
|
||||||
conn = ds.getConnection();
|
|
||||||
smt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
|
||||||
smt.setFetchSize(Integer.MIN_VALUE);
|
|
||||||
rs = smt.executeQuery(sql);
|
|
||||||
|
|
||||||
return fun.apply(rs);
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error("sqlRs has error, sql: {} ", sql);
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
} finally {
|
|
||||||
if (rs != null) {
|
|
||||||
try {
|
|
||||||
rs.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error("error to close result set");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (smt != null) {
|
|
||||||
try {
|
|
||||||
smt.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error("error to close statement");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (conn != null) {
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
logger.error("error to close db connection");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem;
|
|||||||
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem.ColumnItem;
|
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem.ColumnItem;
|
||||||
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem.FieldItem;
|
import com.alibaba.otter.canal.client.adapter.es.config.SchemaItem.FieldItem;
|
||||||
import com.alibaba.otter.canal.client.adapter.support.DatasourceConfig;
|
import com.alibaba.otter.canal.client.adapter.support.DatasourceConfig;
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ES 操作模板
|
* ES 操作模板
|
||||||
@@ -137,7 +138,7 @@ public class ESTemplate {
|
|||||||
(fieldName, value) -> sql.append("_v.").append(fieldName).append("=").append(value).append(" AND "));
|
(fieldName, value) -> sql.append("_v.").append(fieldName).append("=").append(value).append(" AND "));
|
||||||
int len = sql.length();
|
int len = sql.length();
|
||||||
sql.delete(len - 4, len);
|
sql.delete(len - 4, len);
|
||||||
Integer syncCount = (Integer) ESSyncUtil.sqlRS(ds, sql.toString(), rs -> {
|
Integer syncCount = (Integer) Util.sqlRS(ds, sql.toString(), rs -> {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
try {
|
try {
|
||||||
while (rs.next()) {
|
while (rs.next()) {
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class TestConstant {
|
|||||||
public final static String esHosts = "127.0.0.1:9300";
|
public final static String esHosts = "127.0.0.1:9300";
|
||||||
public final static String clusterName = "elasticsearch";
|
public final static String clusterName = "elasticsearch";
|
||||||
|
|
||||||
public static DruidDataSource dataSource;
|
public final static DruidDataSource dataSource;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
dataSource = new DruidDataSource();
|
dataSource = new DruidDataSource();
|
||||||
|
|||||||
@@ -6,9 +6,7 @@ import java.text.SimpleDateFormat;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
@@ -40,10 +38,9 @@ public class HbaseEtlService {
|
|||||||
|
|
||||||
private static Logger logger = LoggerFactory.getLogger(HbaseEtlService.class);
|
private static Logger logger = LoggerFactory.getLogger(HbaseEtlService.class);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 建表
|
* 建表
|
||||||
*
|
*
|
||||||
* @param hbaseTemplate
|
* @param hbaseTemplate
|
||||||
* @param config
|
* @param config
|
||||||
*/
|
*/
|
||||||
@@ -62,7 +59,7 @@ public class HbaseEtlService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 导入数据
|
* 导入数据
|
||||||
*
|
*
|
||||||
* @param ds 数据源
|
* @param ds 数据源
|
||||||
* @param hbaseTemplate hbaseTemplate
|
* @param hbaseTemplate hbaseTemplate
|
||||||
* @param config 配置
|
* @param config 配置
|
||||||
@@ -154,7 +151,20 @@ public class HbaseEtlService {
|
|||||||
if (cnt >= 10000) {
|
if (cnt >= 10000) {
|
||||||
int threadCount = 3;
|
int threadCount = 3;
|
||||||
long perThreadCnt = cnt / threadCount;
|
long perThreadCnt = cnt / threadCount;
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
ExecutorService executor = new ThreadPoolExecutor(threadCount,
|
||||||
|
threadCount,
|
||||||
|
5000L,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
new SynchronousQueue<>(),
|
||||||
|
(r, exe) -> {
|
||||||
|
if (!exe.isShutdown()) {
|
||||||
|
try {
|
||||||
|
exe.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
List<Future<Boolean>> futures = new ArrayList<>(threadCount);
|
List<Future<Boolean>> futures = new ArrayList<>(threadCount);
|
||||||
for (int i = 0; i < threadCount; i++) {
|
for (int i = 0; i < threadCount; i++) {
|
||||||
long offset = i * perThreadCnt;
|
long offset = i * perThreadCnt;
|
||||||
@@ -201,7 +211,7 @@ public class HbaseEtlService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行导入
|
* 执行导入
|
||||||
*
|
*
|
||||||
* @param ds
|
* @param ds
|
||||||
* @param sql
|
* @param sql
|
||||||
* @param hbaseMapping
|
* @param hbaseMapping
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ import com.alibaba.otter.canal.client.adapter.support.Dml;
|
|||||||
*/
|
*/
|
||||||
public class HbaseSyncService {
|
public class HbaseSyncService {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(this.getClass());
|
private static Logger logger = LoggerFactory.getLogger(HbaseSyncService.class);
|
||||||
|
|
||||||
private HbaseTemplate hbaseTemplate; // HBase操作模板
|
private HbaseTemplate hbaseTemplate; // HBase操作模板
|
||||||
|
|
||||||
public HbaseSyncService(HbaseTemplate hbaseTemplate){
|
public HbaseSyncService(HbaseTemplate hbaseTemplate){
|
||||||
this.hbaseTemplate = hbaseTemplate;
|
this.hbaseTemplate = hbaseTemplate;
|
||||||
@@ -140,7 +140,7 @@ public class HbaseSyncService {
|
|||||||
Integer.parseInt((String) entry.getValue()));
|
Integer.parseInt((String) entry.getValue()));
|
||||||
bytes = Bytes.toBytes(v);
|
bytes = Bytes.toBytes(v);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
// ignore
|
logger.error(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,10 @@ import java.math.RoundingMode;
|
|||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.client.adapter.support.Util;
|
|
||||||
import org.apache.hadoop.hbase.util.Bytes;
|
import org.apache.hadoop.hbase.util.Bytes;
|
||||||
import org.joda.time.DateTime;
|
|
||||||
|
|
||||||
|
import com.alibaba.otter.canal.client.adapter.support.Util;
|
||||||
import com.google.common.math.LongMath;
|
import com.google.common.math.LongMath;
|
||||||
import org.joda.time.DateTimeZone;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Phoenix类型转换工具类
|
* Phoenix类型转换工具类
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class EtlLock {
|
|||||||
|
|
||||||
private static final Map<String, InterProcessMutex> DISTRIBUTED_LOCK = new ConcurrentHashMap<>();
|
private static final Map<String, InterProcessMutex> DISTRIBUTED_LOCK = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static Mode mode = Mode.LOCAL;
|
private Mode mode = Mode.LOCAL;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private CuratorClient curatorClient;
|
private CuratorClient curatorClient;
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ public class SyncSwitch {
|
|||||||
|
|
||||||
private static final Map<String, BooleanMutex> DISTRIBUTED_LOCK = new ConcurrentHashMap<>();
|
private static final Map<String, BooleanMutex> DISTRIBUTED_LOCK = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
private static Mode mode = Mode.LOCAL;
|
private Mode mode = Mode.LOCAL;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
private AdapterCanalConfig adapterCanalConfig;
|
private AdapterCanalConfig adapterCanalConfig;
|
||||||
@@ -165,20 +165,20 @@ public class SyncSwitch {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean status(String destination) {
|
public boolean status(String destination) {
|
||||||
if (mode == Mode.LOCAL) {
|
if (mode == Mode.LOCAL) {
|
||||||
BooleanMutex mutex = LOCAL_LOCK.get(destination);
|
BooleanMutex mutex = LOCAL_LOCK.get(destination);
|
||||||
if (mutex != null) {
|
if (mutex != null) {
|
||||||
return mutex.state();
|
return mutex.state();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
BooleanMutex mutex = DISTRIBUTED_LOCK.get(destination);
|
BooleanMutex mutex = DISTRIBUTED_LOCK.get(destination);
|
||||||
if (mutex != null) {
|
if (mutex != null) {
|
||||||
return mutex.state();
|
return mutex.state();
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,7 @@ package com.alibaba.otter.canal.adapter.launcher.loader;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -43,7 +40,21 @@ public abstract class AbstractCanalAdapterWorker {
|
|||||||
|
|
||||||
public AbstractCanalAdapterWorker(List<List<OuterAdapter>> canalOuterAdapters){
|
public AbstractCanalAdapterWorker(List<List<OuterAdapter>> canalOuterAdapters){
|
||||||
this.canalOuterAdapters = canalOuterAdapters;
|
this.canalOuterAdapters = canalOuterAdapters;
|
||||||
this.groupInnerExecutorService = Executors.newFixedThreadPool(canalOuterAdapters.size());
|
int adaptersSize = canalOuterAdapters.size();
|
||||||
|
this.groupInnerExecutorService = new ThreadPoolExecutor(adaptersSize,
|
||||||
|
adaptersSize,
|
||||||
|
5000L,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
new SynchronousQueue<>(),
|
||||||
|
(r, exe) -> {
|
||||||
|
if (!exe.isShutdown()) {
|
||||||
|
try {
|
||||||
|
exe.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
syncSwitch = (SyncSwitch) SpringContext.getBean(SyncSwitch.class);
|
syncSwitch = (SyncSwitch) SpringContext.getBean(SyncSwitch.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
package com.alibaba.otter.canal.adapter.launcher.loader;
|
package com.alibaba.otter.canal.adapter.launcher.loader;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.kafka.common.errors.WakeupException;
|
import org.apache.kafka.common.errors.WakeupException;
|
||||||
|
|
||||||
@@ -44,12 +42,22 @@ public class CanalAdapterKafkaWorker extends AbstractCanalAdapterWorker {
|
|||||||
protected void process() {
|
protected void process() {
|
||||||
while (!running) {
|
while (!running) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(500);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExecutorService workerExecutor = Executors.newSingleThreadExecutor();
|
ExecutorService workerExecutor = new ThreadPoolExecutor(1, 1,
|
||||||
|
5000L, TimeUnit.MILLISECONDS,
|
||||||
|
new SynchronousQueue<>(), (r, exe) -> {
|
||||||
|
if (!exe.isShutdown()) {
|
||||||
|
try {
|
||||||
|
exe.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
//ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
int retry = canalClientConfig.getRetries() == null
|
int retry = canalClientConfig.getRetries() == null
|
||||||
|| canalClientConfig.getRetries() == 0 ? 1 : canalClientConfig.getRetries();
|
|| canalClientConfig.getRetries() == 0 ? 1 : canalClientConfig.getRetries();
|
||||||
long timeout = canalClientConfig.getTimeout() == null ? 30000 : canalClientConfig.getTimeout(); // 默认超时30秒
|
long timeout = canalClientConfig.getTimeout() == null ? 30000 : canalClientConfig.getTimeout(); // 默认超时30秒
|
||||||
@@ -63,8 +71,8 @@ public class CanalAdapterKafkaWorker extends AbstractCanalAdapterWorker {
|
|||||||
connector.subscribe();
|
connector.subscribe();
|
||||||
logger.info("=============> Subscribe topic: {} succeed <=============", this.topic);
|
logger.info("=============> Subscribe topic: {} succeed <=============", this.topic);
|
||||||
while (running) {
|
while (running) {
|
||||||
Boolean status = syncSwitch.status(canalDestination);
|
boolean status = syncSwitch.status(canalDestination);
|
||||||
if (status != null && !status) {
|
if (!status) {
|
||||||
connector.disconnect();
|
connector.disconnect();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -85,6 +93,8 @@ public class CanalAdapterKafkaWorker extends AbstractCanalAdapterWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workerExecutor.shutdown();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connector.unsubscribe();
|
connector.unsubscribe();
|
||||||
} catch (WakeupException e) {
|
} catch (WakeupException e) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import java.net.SocketAddress;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -176,40 +176,32 @@ public class CanalAdapterLoader {
|
|||||||
public void destroy() {
|
public void destroy() {
|
||||||
if (!canalWorkers.isEmpty()) {
|
if (!canalWorkers.isEmpty()) {
|
||||||
ExecutorService stopExecutorService = Executors.newFixedThreadPool(canalWorkers.size());
|
ExecutorService stopExecutorService = Executors.newFixedThreadPool(canalWorkers.size());
|
||||||
List<Future<Boolean>> futures = new ArrayList<>();
|
|
||||||
for (CanalAdapterWorker canalAdapterWorker : canalWorkers.values()) {
|
for (CanalAdapterWorker canalAdapterWorker : canalWorkers.values()) {
|
||||||
futures.add(stopExecutorService.submit(() -> {
|
stopExecutorService.execute(canalAdapterWorker::stop);
|
||||||
canalAdapterWorker.stop();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
futures.forEach(future -> {
|
stopExecutorService.shutdown();
|
||||||
try {
|
try {
|
||||||
future.get();
|
while (!stopExecutorService.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||||
} catch (Exception e) {
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
});
|
} catch (InterruptedException e) {
|
||||||
stopExecutorService.shutdown();
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!canalMQWorker.isEmpty()) {
|
if (!canalMQWorker.isEmpty()) {
|
||||||
ExecutorService stopMQWorkerService = Executors.newFixedThreadPool(canalMQWorker.size());
|
ExecutorService stopMQWorkerService = Executors.newFixedThreadPool(canalMQWorker.size());
|
||||||
List<Future<Boolean>> futures = new ArrayList<>();
|
|
||||||
for (AbstractCanalAdapterWorker canalAdapterMQWorker : canalMQWorker.values()) {
|
for (AbstractCanalAdapterWorker canalAdapterMQWorker : canalMQWorker.values()) {
|
||||||
futures.add(stopMQWorkerService.submit(() -> {
|
stopMQWorkerService.execute(canalAdapterMQWorker::stop);
|
||||||
canalAdapterMQWorker.stop();
|
|
||||||
return true;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
futures.forEach(future -> {
|
stopMQWorkerService.shutdown();
|
||||||
try {
|
try {
|
||||||
future.get();
|
while (!stopMQWorkerService.awaitTermination(1, TimeUnit.SECONDS)) {
|
||||||
} catch (Exception e) {
|
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
});
|
} catch (InterruptedException e) {
|
||||||
stopMQWorkerService.shutdown();
|
// ignore
|
||||||
|
}
|
||||||
}
|
}
|
||||||
logger.info("All canal adapters destroyed");
|
logger.info("All canal adapters destroyed");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package com.alibaba.otter.canal.adapter.launcher.loader;
|
package com.alibaba.otter.canal.adapter.launcher.loader;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import org.apache.kafka.common.errors.WakeupException;
|
import org.apache.kafka.common.errors.WakeupException;
|
||||||
|
|
||||||
@@ -49,8 +48,22 @@ public class CanalAdapterRocketMQWorker extends AbstractCanalAdapterWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutorService workerExecutor = Executors.newSingleThreadExecutor();
|
ExecutorService workerExecutor = new ThreadPoolExecutor(1,
|
||||||
int retry = canalClientConfig.getRetries() == null || canalClientConfig.getRetries() == 0 ? 1 : canalClientConfig.getRetries();
|
1,
|
||||||
|
5000L,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
new SynchronousQueue<>(),
|
||||||
|
(r, exe) -> {
|
||||||
|
if (!exe.isShutdown()) {
|
||||||
|
try {
|
||||||
|
exe.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
int retry = canalClientConfig.getRetries() == null
|
||||||
|
|| canalClientConfig.getRetries() == 0 ? 1 : canalClientConfig.getRetries();
|
||||||
long timeout = canalClientConfig.getTimeout() == null ? 30000 : canalClientConfig.getTimeout(); // 默认超时30秒
|
long timeout = canalClientConfig.getTimeout() == null ? 30000 : canalClientConfig.getTimeout(); // 默认超时30秒
|
||||||
|
|
||||||
while (running) {
|
while (running) {
|
||||||
@@ -62,8 +75,8 @@ public class CanalAdapterRocketMQWorker extends AbstractCanalAdapterWorker {
|
|||||||
connector.subscribe();
|
connector.subscribe();
|
||||||
logger.info("=============> Subscribe topic: {} succeed<=============", this.topic);
|
logger.info("=============> Subscribe topic: {} succeed<=============", this.topic);
|
||||||
while (running) {
|
while (running) {
|
||||||
Boolean status = syncSwitch.status(canalDestination);
|
boolean status = syncSwitch.status(canalDestination);
|
||||||
if (status != null && !status) {
|
if (!status) {
|
||||||
connector.disconnect();
|
connector.disconnect();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -84,6 +97,8 @@ public class CanalAdapterRocketMQWorker extends AbstractCanalAdapterWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
workerExecutor.shutdown();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
connector.unsubscribe();
|
connector.unsubscribe();
|
||||||
} catch (WakeupException e) {
|
} catch (WakeupException e) {
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ public class CanalAdapterWorker extends AbstractCanalAdapterWorker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Throwable e) {
|
||||||
logger.error("process error!", e);
|
logger.error("process error!", e);
|
||||||
} finally {
|
} finally {
|
||||||
connector.disconnect();
|
connector.disconnect();
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.alibaba.otter.canal.adapter.launcher.monitor;
|
package com.alibaba.otter.canal.adapter.launcher.monitor;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
@@ -68,7 +70,7 @@ public class ApplicationConfigMonitor {
|
|||||||
super.onFileChange(file);
|
super.onFileChange(file);
|
||||||
try {
|
try {
|
||||||
// 检查yml格式
|
// 检查yml格式
|
||||||
new Yaml().loadAs(new FileReader(file), Map.class);
|
new Yaml().loadAs(new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8), Map.class);
|
||||||
|
|
||||||
canalAdapterService.destroy();
|
canalAdapterService.destroy();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.alibaba.otter.canal.adapter.launcher.monitor.remote;
|
package com.alibaba.otter.canal.adapter.launcher.monitor.remote;
|
||||||
|
|
||||||
import java.io.FileWriter;
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
@@ -35,7 +37,7 @@ public class DbRemoteConfigLoader implements RemoteConfigLoader {
|
|||||||
|
|
||||||
private DruidDataSource dataSource;
|
private DruidDataSource dataSource;
|
||||||
|
|
||||||
private static volatile long currentConfigTimestamp = 0;
|
private volatile long currentConfigTimestamp = 0;
|
||||||
private Map<String, ConfigItem> remoteAdapterConfigs = new MapMaker().makeMap();
|
private Map<String, ConfigItem> remoteAdapterConfigs = new MapMaker().makeMap();
|
||||||
|
|
||||||
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(2,
|
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(2,
|
||||||
@@ -115,7 +117,10 @@ public class DbRemoteConfigLoader implements RemoteConfigLoader {
|
|||||||
* @param content 文件内容
|
* @param content 文件内容
|
||||||
*/
|
*/
|
||||||
private void overrideLocalCanalConfig(String content) {
|
private void overrideLocalCanalConfig(String content) {
|
||||||
try (FileWriter writer = new FileWriter(CommonUtils.getConfPath() + "application.yml")) {
|
|
||||||
|
try (OutputStreamWriter writer = new OutputStreamWriter(
|
||||||
|
new FileOutputStream(CommonUtils.getConfPath() + "application.yml"),
|
||||||
|
StandardCharsets.UTF_8)) {
|
||||||
writer.write(content);
|
writer.write(content);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package com.alibaba.otter.canal.adapter.launcher.monitor.remote;
|
package com.alibaba.otter.canal.adapter.launcher.monitor.remote;
|
||||||
|
|
||||||
import com.alibaba.otter.canal.common.utils.CommonUtils;
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.File;
|
import com.alibaba.otter.canal.common.utils.CommonUtils;
|
||||||
import java.io.FileWriter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 远程配置监听器实现
|
* 远程配置监听器实现
|
||||||
@@ -35,7 +38,9 @@ public class RemoteAdapterMonitorImpl implements RemoteAdapterMonitor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
String name = configItem.getName();
|
String name = configItem.getName();
|
||||||
try (FileWriter writer = new FileWriter(confPath + category + "/" + configItem.getName())) {
|
try (OutputStreamWriter writer = new OutputStreamWriter(
|
||||||
|
new FileOutputStream(confPath + category + "/" + configItem.getName()),
|
||||||
|
StandardCharsets.UTF_8)) {
|
||||||
writer.write(configItem.getContent());
|
writer.write(configItem.getContent());
|
||||||
writer.flush();
|
writer.flush();
|
||||||
logger.info("## Loaded remote adapter config: {}/{}", category, name);
|
logger.info("## Loaded remote adapter config: {}/{}", category, name);
|
||||||
|
|||||||
@@ -69,16 +69,16 @@ public class CommonRest {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|
||||||
Boolean oriSwitchStatus;
|
boolean oriSwitchStatus;
|
||||||
if (destination != null) {
|
if (destination != null) {
|
||||||
oriSwitchStatus = syncSwitch.status(destination);
|
oriSwitchStatus = syncSwitch.status(destination);
|
||||||
if (oriSwitchStatus != null && oriSwitchStatus) {
|
if (oriSwitchStatus) {
|
||||||
syncSwitch.off(destination);
|
syncSwitch.off(destination);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// task可能为destination,直接锁task
|
// task可能为destination,直接锁task
|
||||||
oriSwitchStatus = syncSwitch.status(task);
|
oriSwitchStatus = syncSwitch.status(task);
|
||||||
if (oriSwitchStatus != null && oriSwitchStatus) {
|
if (oriSwitchStatus) {
|
||||||
syncSwitch.off(task);
|
syncSwitch.off(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,9 +89,9 @@ public class CommonRest {
|
|||||||
}
|
}
|
||||||
return adapter.etl(task, paramArray);
|
return adapter.etl(task, paramArray);
|
||||||
} finally {
|
} finally {
|
||||||
if (destination != null && oriSwitchStatus != null && oriSwitchStatus) {
|
if (destination != null && oriSwitchStatus) {
|
||||||
syncSwitch.on(destination);
|
syncSwitch.on(destination);
|
||||||
} else if (destination == null && oriSwitchStatus != null && oriSwitchStatus) {
|
} else if (destination == null && oriSwitchStatus) {
|
||||||
syncSwitch.on(task);
|
syncSwitch.on(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,7 +102,7 @@ public class CommonRest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* ETL curl http://127.0.0.1:8081/etl/hbase/mytest_person2.yml -X POST
|
* ETL curl http://127.0.0.1:8081/etl/hbase/mytest_person2.yml -X POST
|
||||||
*
|
*
|
||||||
* @param type 类型 hbase, es
|
* @param type 类型 hbase, es
|
||||||
* @param task 任务名对应配置文件名 mytest_person2.yml
|
* @param task 任务名对应配置文件名 mytest_person2.yml
|
||||||
* @param params etl where条件参数, 为空全部导入
|
* @param params etl where条件参数, 为空全部导入
|
||||||
@@ -129,7 +129,7 @@ public class CommonRest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 统计总数 curl http://127.0.0.1:8081/count/hbase/mytest_person2.yml
|
* 统计总数 curl http://127.0.0.1:8081/count/hbase/mytest_person2.yml
|
||||||
*
|
*
|
||||||
* @param type 类型 hbase, es
|
* @param type 类型 hbase, es
|
||||||
* @param task 任务名对应配置文件名 mytest_person2.yml
|
* @param task 任务名对应配置文件名 mytest_person2.yml
|
||||||
* @return
|
* @return
|
||||||
@@ -148,11 +148,11 @@ public class CommonRest {
|
|||||||
Set<String> destinations = adapterCanalConfig.DESTINATIONS;
|
Set<String> destinations = adapterCanalConfig.DESTINATIONS;
|
||||||
for (String destination : destinations) {
|
for (String destination : destinations) {
|
||||||
Map<String, String> resMap = new LinkedHashMap<>();
|
Map<String, String> resMap = new LinkedHashMap<>();
|
||||||
Boolean status = syncSwitch.status(destination);
|
boolean status = syncSwitch.status(destination);
|
||||||
String resStatus = "none";
|
String resStatus;
|
||||||
if (status != null && status) {
|
if (status) {
|
||||||
resStatus = "on";
|
resStatus = "on";
|
||||||
} else if (status != null && !status) {
|
} else {
|
||||||
resStatus = "off";
|
resStatus = "off";
|
||||||
}
|
}
|
||||||
resMap.put("destination", destination);
|
resMap.put("destination", destination);
|
||||||
@@ -164,7 +164,7 @@ public class CommonRest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 实例同步开关 curl http://127.0.0.1:8081/syncSwitch/example/off -X PUT
|
* 实例同步开关 curl http://127.0.0.1:8081/syncSwitch/example/off -X PUT
|
||||||
*
|
*
|
||||||
* @param destination 实例名称
|
* @param destination 实例名称
|
||||||
* @param status 开关状态: off on
|
* @param status 开关状态: off on
|
||||||
* @return
|
* @return
|
||||||
@@ -189,17 +189,17 @@ public class CommonRest {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取实例开关状态 curl http://127.0.0.1:8081/syncSwitch/example
|
* 获取实例开关状态 curl http://127.0.0.1:8081/syncSwitch/example
|
||||||
*
|
*
|
||||||
* @param destination 实例名称
|
* @param destination 实例名称
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@GetMapping("/syncSwitch/{destination}")
|
@GetMapping("/syncSwitch/{destination}")
|
||||||
public Map<String, String> etl(@PathVariable String destination) {
|
public Map<String, String> etl(@PathVariable String destination) {
|
||||||
Boolean status = syncSwitch.status(destination);
|
boolean status = syncSwitch.status(destination);
|
||||||
String resStatus = "none";
|
String resStatus;
|
||||||
if (status != null && status) {
|
if (status) {
|
||||||
resStatus = "on";
|
resStatus = "on";
|
||||||
} else if (status != null && !status) {
|
} else {
|
||||||
resStatus = "off";
|
resStatus = "off";
|
||||||
}
|
}
|
||||||
Map<String, String> res = new LinkedHashMap<>();
|
Map<String, String> res = new LinkedHashMap<>();
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.alibaba.otter.canal.client.adapter.rdb.config;
|
package com.alibaba.otter.canal.client.adapter.rdb.config;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RDB表映射配置
|
* RDB表映射配置
|
||||||
*
|
*
|
||||||
@@ -21,7 +21,7 @@ public class MappingConfig {
|
|||||||
|
|
||||||
private String outerAdapterKey; // 对应适配器的key
|
private String outerAdapterKey; // 对应适配器的key
|
||||||
|
|
||||||
private Boolean concurrent; // 是否并行同步
|
private boolean concurrent = false; // 是否并行同步
|
||||||
|
|
||||||
private DbMapping dbMapping; // db映射配置
|
private DbMapping dbMapping; // db映射配置
|
||||||
|
|
||||||
@@ -49,11 +49,11 @@ public class MappingConfig {
|
|||||||
this.outerAdapterKey = outerAdapterKey;
|
this.outerAdapterKey = outerAdapterKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean getConcurrent() {
|
public boolean getConcurrent() {
|
||||||
return concurrent == null ? false : concurrent;
|
return concurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setConcurrent(Boolean concurrent) {
|
public void setConcurrent(boolean concurrent) {
|
||||||
this.concurrent = concurrent;
|
this.concurrent = concurrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,11 +87,11 @@ public class MappingConfig {
|
|||||||
|
|
||||||
public static class DbMapping {
|
public static class DbMapping {
|
||||||
|
|
||||||
private Boolean mirrorDb = false; // 是否镜像库
|
private boolean mirrorDb = false; // 是否镜像库
|
||||||
private String database; // 数据库名或schema名
|
private String database; // 数据库名或schema名
|
||||||
private String table; // 表名
|
private String table; // 表名
|
||||||
private Map<String, String> targetPk = new LinkedHashMap<>(); // 目标表主键字段
|
private Map<String, String> targetPk = new LinkedHashMap<>(); // 目标表主键字段
|
||||||
private Boolean mapAll = false; // 映射所有字段
|
private boolean mapAll = false; // 映射所有字段
|
||||||
private String targetDb; // 目标库名
|
private String targetDb; // 目标库名
|
||||||
private String targetTable; // 目标表名
|
private String targetTable; // 目标表名
|
||||||
private Map<String, String> targetColumns; // 目标表字段映射
|
private Map<String, String> targetColumns; // 目标表字段映射
|
||||||
@@ -103,11 +103,11 @@ public class MappingConfig {
|
|||||||
|
|
||||||
private Map<String, String> allMapColumns;
|
private Map<String, String> allMapColumns;
|
||||||
|
|
||||||
public Boolean getMirrorDb() {
|
public boolean getMirrorDb() {
|
||||||
return mirrorDb == null ? false : mirrorDb;
|
return mirrorDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMirrorDb(Boolean mirrorDb) {
|
public void setMirrorDb(boolean mirrorDb) {
|
||||||
this.mirrorDb = mirrorDb;
|
this.mirrorDb = mirrorDb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.*;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
@@ -78,7 +76,20 @@ public class RdbEtlService {
|
|||||||
if (cnt >= 10000) {
|
if (cnt >= 10000) {
|
||||||
int threadCount = 3;
|
int threadCount = 3;
|
||||||
long perThreadCnt = cnt / threadCount;
|
long perThreadCnt = cnt / threadCount;
|
||||||
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
|
ExecutorService executor = new ThreadPoolExecutor(threadCount,
|
||||||
|
threadCount,
|
||||||
|
5000L,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
new SynchronousQueue<>(),
|
||||||
|
(r, exe) -> {
|
||||||
|
if (!exe.isShutdown()) {
|
||||||
|
try {
|
||||||
|
exe.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e1) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
List<Future<Boolean>> futures = new ArrayList<>(threadCount);
|
List<Future<Boolean>> futures = new ArrayList<>(threadCount);
|
||||||
for (int i = 0; i < threadCount; i++) {
|
for (int i = 0; i < threadCount; i++) {
|
||||||
long offset = i * perThreadCnt;
|
long offset = i * perThreadCnt;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -92,17 +92,16 @@ public class DBTest {
|
|||||||
|
|
||||||
private String clob2Str(Clob clob) {
|
private String clob2Str(Clob clob) {
|
||||||
String content = "";
|
String content = "";
|
||||||
try {
|
try (Reader is = clob.getCharacterStream(); BufferedReader buff = new BufferedReader(is)) {
|
||||||
Reader is = clob.getCharacterStream();
|
|
||||||
BufferedReader buff = new BufferedReader(is);
|
|
||||||
String line = buff.readLine();
|
String line = buff.readLine();
|
||||||
StringBuffer sb = new StringBuffer();
|
StringBuilder sb = new StringBuilder();
|
||||||
while (line != null) {
|
while (line != null) {
|
||||||
sb.append(line);
|
sb.append(line);
|
||||||
line = buff.readLine();
|
line = buff.readLine();
|
||||||
}
|
}
|
||||||
content = sb.toString();
|
content = sb.toString();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class TestConstant {
|
|||||||
public final static String jdbcUser = "root";
|
public final static String jdbcUser = "root";
|
||||||
public final static String jdbcPassword = "121212";
|
public final static String jdbcPassword = "121212";
|
||||||
|
|
||||||
public static DruidDataSource dataSource;
|
public final static DruidDataSource dataSource;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
dataSource = new DruidDataSource();
|
dataSource = new DruidDataSource();
|
||||||
|
|||||||
Reference in New Issue
Block a user