kafka producer 修改配置,一个destination可以对应多个kafka topic

This commit is contained in:
rewerma
2018-06-13 13:36:28 +08:00
parent b96e4dd23a
commit efb7b32694
3 changed files with 102 additions and 34 deletions

View File

@@ -1,6 +1,7 @@
package com.alibaba.otter.canal.kafka.producer; package com.alibaba.otter.canal.kafka.producer;
import com.alibaba.otter.canal.kafka.CanalServerStarter; import com.alibaba.otter.canal.kafka.CanalServerStarter;
import com.alibaba.otter.canal.kafka.producer.KafkaProperties.CanalDestination;
import com.alibaba.otter.canal.kafka.producer.KafkaProperties.Topic; import com.alibaba.otter.canal.kafka.producer.KafkaProperties.Topic;
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;
@@ -31,13 +32,15 @@ public class CanalKafkaStarter {
private static CanalKafkaProducer canalKafkaProducer; private static CanalKafkaProducer canalKafkaProducer;
private static KafkaProperties kafkaProperties;
public static void init() { public static void init() {
try { try {
logger.info("## load kafka configurations"); logger.info("## load kafka configurations");
String conf = System.getProperty("kafka.conf", "classpath:kafka.yml"); String conf = System.getProperty("kafka.conf", "classpath:kafka.yml");
KafkaProperties kafkaProperties;
if (conf.startsWith(CLASSPATH_URL_PREFIX)) { if (conf.startsWith(CLASSPATH_URL_PREFIX)) {
conf = StringUtils.substringAfter(conf, CLASSPATH_URL_PREFIX); conf = StringUtils.substringAfter(conf, CLASSPATH_URL_PREFIX);
kafkaProperties = new Yaml().loadAs(CanalKafkaStarter.class.getClassLoader().getResourceAsStream(conf), KafkaProperties.class); kafkaProperties = new Yaml().loadAs(CanalKafkaStarter.class.getClassLoader().getResourceAsStream(conf), KafkaProperties.class);
@@ -50,16 +53,16 @@ public class CanalKafkaStarter {
canalKafkaProducer.init(kafkaProperties); canalKafkaProducer.init(kafkaProperties);
//对应每个instance启动一个worker线程 //对应每个instance启动一个worker线程
List<Topic> topics = kafkaProperties.getTopics(); List<CanalDestination> destinations = kafkaProperties.getCanalDestinations();
executorService = Executors.newFixedThreadPool(topics.size()); executorService = Executors.newFixedThreadPool(destinations.size());
logger.info("## start the kafka workers."); logger.info("## start the kafka workers.");
for (final Topic topic : topics) { for (final CanalDestination destination : destinations) {
executorService.execute(new Runnable() { executorService.execute(new Runnable() {
@Override @Override
public void run() { public void run() {
worker(topic); worker(destination);
} }
}); });
} }
@@ -88,12 +91,12 @@ public class CanalKafkaStarter {
} }
private static void worker(Topic topic) { private static void worker(CanalDestination destination) {
while (!running) ; while (!running) ;
while (!CanalServerStarter.isRunning()) ; //等待server启动完成 while (!CanalServerStarter.isRunning()) ; //等待server启动完成
logger.info("## start the canal consumer: {}.", topic.getCanalDestination()); logger.info("## start the canal consumer: {}.", destination.getCanalDestination());
CanalServerWithEmbedded server = CanalServerWithEmbedded.instance(); CanalServerWithEmbedded server = CanalServerWithEmbedded.instance();
ClientIdentity clientIdentity = new ClientIdentity(topic.getCanalDestination(), (short) 1001, ""); ClientIdentity clientIdentity = new ClientIdentity(destination.getCanalDestination(), (short) 1001, "");
while (running) { while (running) {
try { try {
if (!server.getCanalInstances().containsKey(clientIdentity.getDestination())) { if (!server.getCanalInstances().containsKey(clientIdentity.getDestination())) {
@@ -105,21 +108,23 @@ public class CanalKafkaStarter {
continue; continue;
} }
server.subscribe(clientIdentity); server.subscribe(clientIdentity);
logger.info("## the canal consumer {} is running now ......", topic.getCanalDestination()); logger.info("## the canal consumer {} is running now ......", destination.getCanalDestination());
while (running) { while (running) {
Message message = server.getWithoutAck(clientIdentity, 5 * 1024); // 获取指定数量的数据 Message message = server.getWithoutAck(clientIdentity, kafkaProperties.getCanalBatchSize()); // 获取指定数量的数据
long batchId = message.getId(); long batchId = message.getId();
try { try {
int size = message.getEntries().size(); int size = message.getEntries().size();
if (batchId == -1 || size == 0) { if (batchId != -1 && size != 0) {
try { if (!StringUtils.isEmpty(destination.getTopic())) {
Thread.sleep(1000); Topic topic = new Topic();
} catch (InterruptedException e) { topic.setTopic(destination.getTopic());
//ignore topic.setPartition(destination.getPartition());
destination.getTopics().add(topic);
}
for (Topic topic : destination.getTopics()) {
canalKafkaProducer.send(topic, message); //发送message到所有topic
} }
} else {
canalKafkaProducer.send(topic, message);
} }
if (batchId != -1) { if (batchId != -1) {

View File

@@ -1,7 +1,9 @@
package com.alibaba.otter.canal.kafka.producer; package com.alibaba.otter.canal.kafka.producer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
/** /**
* kafka 配置项 * kafka 配置项
@@ -16,12 +18,23 @@ public class KafkaProperties {
private int lingerMs = 1; private int lingerMs = 1;
private long bufferMemory = 33554432L; private long bufferMemory = 33554432L;
private List<Topic> topics = new ArrayList<Topic>(); private int canalBatchSize = 5;
public static class Topic { private List<CanalDestination> canalDestinations = new ArrayList<CanalDestination>();
public static class CanalDestination {
private String canalDestination;
private String topic; private String topic;
private Integer partition; private Integer partition;
private String canalDestination; private Set<Topic> topics = new HashSet<Topic>();
public String getCanalDestination() {
return canalDestination;
}
public void setCanalDestination(String canalDestination) {
this.canalDestination = canalDestination;
}
public String getTopic() { public String getTopic() {
return topic; return topic;
@@ -39,12 +52,51 @@ public class KafkaProperties {
this.partition = partition; this.partition = partition;
} }
public String getCanalDestination() { public Set<Topic> getTopics() {
return canalDestination; return topics;
} }
public void setCanalDestination(String canalDestination) { public void setTopics(Set<Topic> topics) {
this.canalDestination = canalDestination; this.topics = topics;
}
}
public static class Topic {
private String topic;
private Integer partition;
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public Integer getPartition() {
return partition;
}
public void setPartition(Integer partition) {
this.partition = partition;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Topic topic1 = (Topic) o;
if (topic != null ? !topic.equals(topic1.topic) : topic1.topic != null) return false;
return partition != null ? partition.equals(topic1.partition) : topic1.partition == null;
}
@Override
public int hashCode() {
int result = topic != null ? topic.hashCode() : 0;
result = 31 * result + (partition != null ? partition.hashCode() : 0);
return result;
} }
} }
@@ -88,11 +140,19 @@ public class KafkaProperties {
this.bufferMemory = bufferMemory; this.bufferMemory = bufferMemory;
} }
public List<Topic> getTopics() { public int getCanalBatchSize() {
return topics; return canalBatchSize;
} }
public void setTopics(List<Topic> topics) { public void setCanalBatchSize(int canalBatchSize) {
this.topics = topics; this.canalBatchSize = canalBatchSize;
}
public List<CanalDestination> getCanalDestinations() {
return canalDestinations;
}
public void setCanalDestinations(List<CanalDestination> canalDestinations) {
this.canalDestinations = canalDestinations;
} }
} }

View File

@@ -3,13 +3,16 @@ retries: 0
batchSize: 16384 batchSize: 16384
lingerMs: 1 lingerMs: 1
bufferMemory: 33554432 bufferMemory: 33554432
# canal的批次大小,单位 k
canalBatchSize: 5
topics: canalDestinations:
- topic: example - canalDestination: example
topic: example
partition: partition:
canalDestination: example # 一个destination可以对应多个topic
# - topic: example2 # topics:
# partition: # - topics: example
# canalDestination: example # partition: