mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
@@ -111,11 +111,20 @@ public class CanalClientConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class MQTopic {
|
public static class MQTopic {
|
||||||
|
private String mqMode;
|
||||||
|
|
||||||
private String topic;
|
private String topic;
|
||||||
|
|
||||||
private List<Group> groups = new ArrayList<>();
|
private List<Group> groups = new ArrayList<>();
|
||||||
|
|
||||||
|
public String getMqMode() {
|
||||||
|
return mqMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMqMode(String mqMode) {
|
||||||
|
this.mqMode = mqMode;
|
||||||
|
}
|
||||||
|
|
||||||
public String getTopic() {
|
public String getTopic() {
|
||||||
return topic;
|
return topic;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ 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.CanalClientConfig;
|
||||||
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.ExtensionLoader;
|
import com.alibaba.otter.canal.client.adapter.support.ExtensionLoader;
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ import java.util.concurrent.ExecutorService;
|
|||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RocktMQ外部适配器的加载器
|
* MQ外部适配器的加载器
|
||||||
*
|
*
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
*/
|
*/
|
||||||
@@ -29,8 +30,7 @@ public class CanalAdapterLoader {
|
|||||||
|
|
||||||
private Map<String, CanalAdapterWorker> canalWorkers = new HashMap<>();
|
private Map<String, CanalAdapterWorker> canalWorkers = new HashMap<>();
|
||||||
|
|
||||||
private Map<String, CanalAdapterKafkaWorker> canalKafkaWorkers = new HashMap<>();
|
private Map<String, AbstractCanalAdapterWorker> canalMQWorker = new HashMap<>();
|
||||||
private Map<String, CanalAdapterRocketMQWorker> canalMQWorker = new HashMap<>();
|
|
||||||
|
|
||||||
private ExtensionLoader<CanalOuterAdapter> loader;
|
private ExtensionLoader<CanalOuterAdapter> loader;
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ public class CanalAdapterLoader {
|
|||||||
* 初始化canal-client、 canal-client-rocketmq的适配器
|
* 初始化canal-client、 canal-client-rocketmq的适配器
|
||||||
*/
|
*/
|
||||||
public void init() {
|
public void init() {
|
||||||
// canal instances 和 rocketmq topics 配置不能同时为空
|
// canal instances 和 mq topics 配置不能同时为空
|
||||||
if (canalClientConfig.getCanalInstances() == null && canalClientConfig.getMqTopics() == null) {
|
if (canalClientConfig.getCanalInstances() == null && canalClientConfig.getMqTopics() == null) {
|
||||||
throw new RuntimeException("Blank config property: canalInstances or canalMQTopics");
|
throw new RuntimeException("Blank config property: canalInstances or canalMQTopics");
|
||||||
}
|
}
|
||||||
@@ -58,11 +58,6 @@ public class CanalAdapterLoader {
|
|||||||
}
|
}
|
||||||
String zkHosts = this.canalClientConfig.getZookeeperHosts();
|
String zkHosts = this.canalClientConfig.getZookeeperHosts();
|
||||||
|
|
||||||
// if (zkHosts == null && sa == null) {
|
|
||||||
// throw new RuntimeException("Blank config property: canalServerHost or
|
|
||||||
// zookeeperHosts");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 初始化canal-client的适配器
|
// 初始化canal-client的适配器
|
||||||
if (canalClientConfig.getCanalInstances() != null) {
|
if (canalClientConfig.getCanalInstances() != null) {
|
||||||
for (CanalClientConfig.CanalInstance instance : canalClientConfig.getCanalInstances()) {
|
for (CanalClientConfig.CanalInstance instance : canalClientConfig.getCanalInstances()) {
|
||||||
@@ -96,19 +91,27 @@ public class CanalAdapterLoader {
|
|||||||
List<CanalOuterAdapter> canalOuterAdapters = new ArrayList<>();
|
List<CanalOuterAdapter> canalOuterAdapters = new ArrayList<>();
|
||||||
|
|
||||||
for (CanalOuterAdapterConfiguration config : group.getOutAdapters()) {
|
for (CanalOuterAdapterConfiguration config : group.getOutAdapters()) {
|
||||||
// for (CanalOuterAdapterConfiguration config : adaptor.getOutAdapters()) {
|
|
||||||
loadConnector(config, canalOuterAdapters);
|
loadConnector(config, canalOuterAdapters);
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
canalOuterAdapterGroups.add(canalOuterAdapters);
|
canalOuterAdapterGroups.add(canalOuterAdapters);
|
||||||
|
|
||||||
|
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() + "-" + group.getGroupId(), rocketMQWorker);
|
canalMQWorker.put(topic.getTopic() + "-rocketmq-" + group.getGroupId(), rocketMQWorker);
|
||||||
rocketMQWorker.start();
|
rocketMQWorker.start();
|
||||||
|
} else if ("kafka".equalsIgnoreCase(topic.getMqMode())) {
|
||||||
|
CanalAdapterKafkaWorker canalKafkaWorker = new CanalAdapterKafkaWorker(zkHosts,
|
||||||
|
canalClientConfig.getBootstrapServers(),
|
||||||
|
topic.getTopic(),
|
||||||
|
group.getGroupId(),
|
||||||
|
canalOuterAdapterGroups);
|
||||||
|
canalMQWorker.put(topic.getTopic() + "-kafka-" + group.getGroupId(), canalKafkaWorker);
|
||||||
|
canalKafkaWorker.start();
|
||||||
|
}
|
||||||
logger.info("Start adapter for canal-client rocketmq topic: {} succeed",
|
logger.info("Start adapter for canal-client rocketmq topic: {} succeed",
|
||||||
topic.getTopic() + "-" + group.getGroupId());
|
topic.getTopic() + "-" + group.getGroupId());
|
||||||
}
|
}
|
||||||
@@ -149,15 +152,14 @@ public class CanalAdapterLoader {
|
|||||||
}
|
}
|
||||||
stopExecutorService.shutdown();
|
stopExecutorService.shutdown();
|
||||||
}
|
}
|
||||||
if (canalKafkaWorkers.size() > 0) {
|
if (canalMQWorker.size() > 0) {
|
||||||
ExecutorService stopKafkaExecutorService = Executors.newFixedThreadPool(canalKafkaWorkers.size());
|
ExecutorService stopKafkaExecutorService = Executors.newFixedThreadPool(canalMQWorker.size());
|
||||||
for (CanalAdapterKafkaWorker v : canalKafkaWorkers.values()) {
|
for (AbstractCanalAdapterWorker tmp : canalMQWorker.values()) {
|
||||||
final CanalAdapterKafkaWorker cakw = v;
|
final AbstractCanalAdapterWorker worker = tmp;
|
||||||
stopKafkaExecutorService.submit(new Runnable() {
|
stopKafkaExecutorService.submit(new Runnable() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
cakw.stop();
|
worker.stop();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ canalServerHost: 127.0.0.1:11111
|
|||||||
# - name: hbase
|
# - name: hbase
|
||||||
# hosts: slave1:2181
|
# hosts: slave1:2181
|
||||||
# properties: {znodeParent: "/hbase-unsecure"}
|
# properties: {znodeParent: "/hbase-unsecure"}
|
||||||
|
|
||||||
mqTopics:
|
mqTopics:
|
||||||
|
- mqMode: rocketmq
|
||||||
- topic: example
|
- topic: example
|
||||||
groups:
|
groups:
|
||||||
- groupId: example_g1
|
- groupId: example_g1
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ filterTransactionEntry: true
|
|||||||
canalDestinations:
|
canalDestinations:
|
||||||
- canalDestination: example
|
- canalDestination: example
|
||||||
topic: example
|
topic: example
|
||||||
partition:
|
partition: 0
|
||||||
# 一个destination可以对应多个topic
|
# 一个destination可以对应多个topic
|
||||||
#topics:
|
#topics:
|
||||||
# - topic: example
|
# - topic: example
|
||||||
|
|||||||
@@ -35,14 +35,13 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void send(MQProperties.Topic topic, com.alibaba.otter.canal.protocol.Message data) {
|
public void send(final MQProperties.Topic topic, com.alibaba.otter.canal.protocol.Message data) {
|
||||||
try {
|
try {
|
||||||
Message message = new Message(topic.getTopic(), CanalMessageSerializer.serializer(data));
|
Message message = new Message(topic.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 index = (arg.hashCode() % mqs.size());
|
return mqs.get(topic.getPartition());
|
||||||
return mqs.get(1);
|
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
|
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user