add proxy for SPI (#4520)

* 测试类报错

* add proxy for SPI
This commit is contained in:
rewerma
2022-12-06 17:35:30 +08:00
committed by GitHub
parent b937ee613d
commit cd798b71e9
6 changed files with 271 additions and 37 deletions

View File

@@ -0,0 +1,87 @@
package com.alibaba.otter.canal.client.adapter;
import com.alibaba.otter.canal.client.adapter.support.Dml;
import com.alibaba.otter.canal.client.adapter.support.EtlResult;
import com.alibaba.otter.canal.client.adapter.support.OuterAdapterConfig;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class ProxyOuterAdapter implements OuterAdapter {
private OuterAdapter outerAdapter;
public ProxyOuterAdapter(OuterAdapter outerAdapter) {
this.outerAdapter = outerAdapter;
}
private ClassLoader changeCL() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(outerAdapter.getClass().getClassLoader());
return cl;
}
private void revertCL(ClassLoader cl) {
Thread.currentThread().setContextClassLoader(cl);
}
@Override
public void init(OuterAdapterConfig configuration, Properties envProperties) {
ClassLoader cl = changeCL();
try {
outerAdapter.init(configuration, envProperties);
} finally {
revertCL(cl);
}
}
@Override
public void sync(List<Dml> dmls) {
ClassLoader cl = changeCL();
try {
outerAdapter.sync(dmls);
} finally {
revertCL(cl);
}
}
@Override
public void destroy() {
ClassLoader cl = changeCL();
try {
outerAdapter.destroy();
} finally {
revertCL(cl);
}
}
@Override
public EtlResult etl(String task, List<String> params) {
ClassLoader cl = changeCL();
try {
return OuterAdapter.super.etl(task, params);
} finally {
revertCL(cl);
}
}
@Override
public Map<String, Object> count(String task) {
ClassLoader cl = changeCL();
try {
return OuterAdapter.super.count(task);
} finally {
revertCL(cl);
}
}
@Override
public String getDestination(String task) {
ClassLoader cl = changeCL();
try {
return OuterAdapter.super.getDestination(task);
} finally {
revertCL(cl);
}
}
}

View File

@@ -1,5 +1,6 @@
package com.alibaba.otter.canal.adapter.launcher.loader; package com.alibaba.otter.canal.adapter.launcher.loader;
import com.alibaba.otter.canal.connector.core.spi.ProxyCanalMsgConsumer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
@@ -52,7 +53,7 @@ public class AdapterProcessor {
private SyncSwitch syncSwitch; private SyncSwitch syncSwitch;
public AdapterProcessor(CanalClientConfig canalClientConfig, String destination, String groupId, public AdapterProcessor(CanalClientConfig canalClientConfig, String destination, String groupId,
List<List<OuterAdapter>> canalOuterAdapters){ List<List<OuterAdapter>> canalOuterAdapters) {
this.canalClientConfig = canalClientConfig; this.canalClientConfig = canalClientConfig;
this.canalDestination = destination; this.canalDestination = destination;
this.groupId = groupId; this.groupId = groupId;
@@ -63,17 +64,15 @@ public class AdapterProcessor {
// load connector consumer // load connector consumer
ExtensionLoader<CanalMsgConsumer> loader = new ExtensionLoader<>(CanalMsgConsumer.class); ExtensionLoader<CanalMsgConsumer> loader = new ExtensionLoader<>(CanalMsgConsumer.class);
canalMsgConsumer = loader canalMsgConsumer = new ProxyCanalMsgConsumer(loader
.getExtension(canalClientConfig.getMode().toLowerCase(),destination ,CONNECTOR_SPI_DIR, CONNECTOR_STANDBY_SPI_DIR); .getExtension(canalClientConfig.getMode().toLowerCase(), destination, CONNECTOR_SPI_DIR,
CONNECTOR_STANDBY_SPI_DIR));
Properties properties = canalClientConfig.getConsumerProperties(); Properties properties = canalClientConfig.getConsumerProperties();
properties.put(CanalConstants.CANAL_MQ_FLAT_MESSAGE, canalClientConfig.getFlatMessage()); properties.put(CanalConstants.CANAL_MQ_FLAT_MESSAGE, canalClientConfig.getFlatMessage());
properties.put(CanalConstants.CANAL_ALIYUN_ACCESS_KEY, canalClientConfig.getAccessKey()); properties.put(CanalConstants.CANAL_ALIYUN_ACCESS_KEY, canalClientConfig.getAccessKey());
properties.put(CanalConstants.CANAL_ALIYUN_SECRET_KEY, canalClientConfig.getSecretKey()); properties.put(CanalConstants.CANAL_ALIYUN_SECRET_KEY, canalClientConfig.getSecretKey());
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(canalMsgConsumer.getClass().getClassLoader());
canalMsgConsumer.init(properties, canalDestination, groupId); canalMsgConsumer.init(properties, canalDestination, groupId);
Thread.currentThread().setContextClassLoader(cl);
} }
public void start() { public void start() {

View File

@@ -1,5 +1,6 @@
package com.alibaba.otter.canal.adapter.launcher.loader; package com.alibaba.otter.canal.adapter.launcher.loader;
import com.alibaba.otter.canal.client.adapter.ProxyOuterAdapter;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -87,11 +88,8 @@ public class CanalAdapterLoader {
private void loadAdapter(OuterAdapterConfig config, List<OuterAdapter> canalOutConnectors) { private void loadAdapter(OuterAdapterConfig config, List<OuterAdapter> canalOutConnectors) {
try { try {
OuterAdapter adapter; OuterAdapter adapter;
adapter = loader.getExtension(config.getName(), config.getKey()); adapter = new ProxyOuterAdapter(loader.getExtension(config.getName(), config.getKey()));
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// 替换ClassLoader
Thread.currentThread().setContextClassLoader(adapter.getClass().getClassLoader());
Environment env = (Environment) SpringContext.getBean(Environment.class); Environment env = (Environment) SpringContext.getBean(Environment.class);
Properties evnProperties = null; Properties evnProperties = null;
if (env instanceof StandardEnvironment) { if (env instanceof StandardEnvironment) {
@@ -109,7 +107,6 @@ public class CanalAdapterLoader {
} }
} }
adapter.init(config, evnProperties); adapter.init(config, evnProperties);
Thread.currentThread().setContextClassLoader(cl);
canalOutConnectors.add(adapter); canalOutConnectors.add(adapter);
logger.info("Load canal adapter: {} succeed", config.getName()); logger.info("Load canal adapter: {} succeed", config.getName());
} catch (Exception e) { } catch (Exception e) {

View File

@@ -0,0 +1,66 @@
package com.alibaba.otter.canal.connector.core.spi;
import com.alibaba.otter.canal.connector.core.config.MQProperties;
import com.alibaba.otter.canal.connector.core.producer.MQDestination;
import com.alibaba.otter.canal.connector.core.util.Callback;
import com.alibaba.otter.canal.protocol.Message;
import java.util.Properties;
public class ProxyCanalMQProducer implements CanalMQProducer {
private CanalMQProducer canalMQProducer;
public ProxyCanalMQProducer(CanalMQProducer canalMQProducer) {
this.canalMQProducer = canalMQProducer;
}
private ClassLoader changeCL() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(canalMQProducer.getClass().getClassLoader());
return cl;
}
private void revertCL(ClassLoader cl) {
Thread.currentThread().setContextClassLoader(cl);
}
@Override
public void init(Properties properties) {
ClassLoader cl = changeCL();
try {
canalMQProducer.init(properties);
} finally {
revertCL(cl);
}
}
@Override
public MQProperties getMqProperties() {
ClassLoader cl = changeCL();
try {
return canalMQProducer.getMqProperties();
} finally {
revertCL(cl);
}
}
@Override
public void send(MQDestination canalDestination, Message message, Callback callback) {
ClassLoader cl = changeCL();
try {
canalMQProducer.send(canalDestination, message, callback);
} finally {
revertCL(cl);
}
}
@Override
public void stop() {
ClassLoader cl = changeCL();
try {
canalMQProducer.stop();
} finally {
revertCL(cl);
}
}
}

View File

@@ -0,0 +1,86 @@
package com.alibaba.otter.canal.connector.core.spi;
import com.alibaba.otter.canal.connector.core.consumer.CommonMessage;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
public class ProxyCanalMsgConsumer implements CanalMsgConsumer {
private CanalMsgConsumer canalMsgConsumer;
public ProxyCanalMsgConsumer(CanalMsgConsumer canalMsgConsumer) {
this.canalMsgConsumer = canalMsgConsumer;
}
private ClassLoader changeCL() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(canalMsgConsumer.getClass().getClassLoader());
return cl;
}
private void revertCL(ClassLoader cl) {
Thread.currentThread().setContextClassLoader(cl);
}
@Override
public void init(Properties properties, String topic, String groupId) {
ClassLoader cl = changeCL();
try {
canalMsgConsumer.init(properties, topic, groupId);
} finally {
revertCL(cl);
}
}
@Override
public void connect() {
ClassLoader cl = changeCL();
try {
canalMsgConsumer.connect();
} finally {
revertCL(cl);
}
}
@Override
public List<CommonMessage> getMessage(Long timeout, TimeUnit unit) {
ClassLoader cl = changeCL();
try {
return canalMsgConsumer.getMessage(timeout, unit);
} finally {
revertCL(cl);
}
}
@Override
public void ack() {
ClassLoader cl = changeCL();
try {
canalMsgConsumer.ack();
} finally {
revertCL(cl);
}
}
@Override
public void rollback() {
ClassLoader cl = changeCL();
try {
canalMsgConsumer.rollback();
} finally {
revertCL(cl);
}
}
@Override
public void disconnect() {
ClassLoader cl = changeCL();
try {
canalMsgConsumer.disconnect();
} finally {
revertCL(cl);
}
}
}

View File

@@ -1,5 +1,6 @@
package com.alibaba.otter.canal.deployer; package com.alibaba.otter.canal.deployer;
import com.alibaba.otter.canal.connector.core.spi.ProxyCanalMQProducer;
import java.util.Properties; import java.util.Properties;
import com.alibaba.otter.canal.connector.core.config.MQProperties; import com.alibaba.otter.canal.connector.core.config.MQProperties;
@@ -35,7 +36,7 @@ public class CanalStarter {
private CanalAdminWithNetty canalAdmin; private CanalAdminWithNetty canalAdmin;
public CanalStarter(Properties properties){ public CanalStarter(Properties properties) {
this.properties = properties; this.properties = properties;
} }
@@ -67,10 +68,8 @@ public class CanalStarter {
canalMQProducer = loader canalMQProducer = loader
.getExtension(serverMode.toLowerCase(), CONNECTOR_SPI_DIR, CONNECTOR_STANDBY_SPI_DIR); .getExtension(serverMode.toLowerCase(), CONNECTOR_SPI_DIR, CONNECTOR_STANDBY_SPI_DIR);
if (canalMQProducer != null) { if (canalMQProducer != null) {
ClassLoader cl = Thread.currentThread().getContextClassLoader(); canalMQProducer = new ProxyCanalMQProducer(canalMQProducer);
Thread.currentThread().setContextClassLoader(canalMQProducer.getClass().getClassLoader());
canalMQProducer.init(properties); canalMQProducer.init(properties);
Thread.currentThread().setContextClassLoader(cl);
} }
} }