mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
fixed kafka performance
This commit is contained in:
@@ -17,9 +17,9 @@ import com.alibaba.otter.canal.deployer.CanalController;
|
||||
*/
|
||||
public class CanalServerStarter {
|
||||
|
||||
private static final String CLASSPATH_URL_PREFIX = "classpath:";
|
||||
private static final Logger logger = LoggerFactory.getLogger(CanalServerStarter.class);
|
||||
private volatile static boolean running = false;
|
||||
private static final String CLASSPATH_URL_PREFIX = "classpath:";
|
||||
private static final Logger logger = LoggerFactory.getLogger(CanalServerStarter.class);
|
||||
private volatile static boolean running = false;
|
||||
|
||||
public static void init() {
|
||||
try {
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.alibaba.otter.canal.kafka.producer;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.google.protobuf.ByteString;
|
||||
import org.apache.kafka.clients.producer.KafkaProducer;
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
@@ -12,7 +11,6 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.otter.canal.kafka.producer.KafkaProperties.Topic;
|
||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||
import com.alibaba.otter.canal.protocol.Message;
|
||||
|
||||
/**
|
||||
@@ -52,31 +50,32 @@ public class CanalKafkaProducer {
|
||||
}
|
||||
|
||||
public void send(Topic topic, Message message) throws IOException {
|
||||
boolean valid = false;
|
||||
if (message != null) {
|
||||
if (message.isRaw() && !message.getRawEntries().isEmpty()) {
|
||||
for (ByteString byteString : message.getRawEntries()) {
|
||||
CanalEntry.Entry entry = CanalEntry.Entry.parseFrom(byteString);
|
||||
if (entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONBEGIN
|
||||
&& entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONEND) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!message.getEntries().isEmpty()){
|
||||
for (CanalEntry.Entry entry : message.getEntries()) {
|
||||
if (entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONBEGIN
|
||||
&& entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONEND) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
// set canal.instance.filter.transaction.entry = true
|
||||
|
||||
// boolean valid = false;
|
||||
// if (message != null) {
|
||||
// if (message.isRaw() && !message.getRawEntries().isEmpty()) {
|
||||
// for (ByteString byteString : message.getRawEntries()) {
|
||||
// CanalEntry.Entry entry = CanalEntry.Entry.parseFrom(byteString);
|
||||
// if (entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONBEGIN
|
||||
// && entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONEND) {
|
||||
// valid = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// } else if (!message.getEntries().isEmpty()){
|
||||
// for (CanalEntry.Entry entry : message.getEntries()) {
|
||||
// if (entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONBEGIN
|
||||
// && entry.getEntryType() != CanalEntry.EntryType.TRANSACTIONEND) {
|
||||
// valid = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// if (!valid) {
|
||||
// return;
|
||||
// }
|
||||
ProducerRecord<String, Message> record;
|
||||
if (topic.getPartition() != null) {
|
||||
record = new ProducerRecord<String, Message>(topic.getTopic(), topic.getPartition(), null, message);
|
||||
|
||||
@@ -52,7 +52,10 @@ public class CanalKafkaStarter {
|
||||
// 初始化 kafka producer
|
||||
canalKafkaProducer = new CanalKafkaProducer();
|
||||
canalKafkaProducer.init(kafkaProperties);
|
||||
|
||||
// set filterTransactionEntry
|
||||
if (kafkaProperties.isFilterTransactionEntry()) {
|
||||
System.setProperty("canal.instance.filter.transaction.entry", "true");
|
||||
}
|
||||
// 对应每个instance启动一个worker线程
|
||||
List<CanalDestination> destinations = kafkaProperties.getCanalDestinations();
|
||||
|
||||
|
||||
@@ -13,15 +13,15 @@ import java.util.Set;
|
||||
*/
|
||||
public class KafkaProperties {
|
||||
|
||||
private String servers = "localhost:6667";
|
||||
private int retries = 0;
|
||||
private int batchSize = 16384;
|
||||
private int lingerMs = 1;
|
||||
private long bufferMemory = 33554432L;
|
||||
private String servers = "localhost:6667";
|
||||
private int retries = 0;
|
||||
private int batchSize = 16384;
|
||||
private int lingerMs = 1;
|
||||
private long bufferMemory = 33554432L;
|
||||
private boolean filterTransactionEntry = true;
|
||||
private int canalBatchSize = 5;
|
||||
|
||||
private int canalBatchSize = 5;
|
||||
|
||||
private List<CanalDestination> canalDestinations = new ArrayList<CanalDestination>();
|
||||
private List<CanalDestination> canalDestinations = new ArrayList<CanalDestination>();
|
||||
|
||||
public static class CanalDestination {
|
||||
|
||||
@@ -158,4 +158,13 @@ public class KafkaProperties {
|
||||
public void setCanalDestinations(List<CanalDestination> canalDestinations) {
|
||||
this.canalDestinations = canalDestinations;
|
||||
}
|
||||
|
||||
public boolean isFilterTransactionEntry() {
|
||||
return filterTransactionEntry;
|
||||
}
|
||||
|
||||
public void setFilterTransactionEntry(boolean filterTransactionEntry) {
|
||||
this.filterTransactionEntry = filterTransactionEntry;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
package com.alibaba.otter.canal.kafka.producer;
|
||||
|
||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||
import com.alibaba.otter.canal.protocol.CanalPacket;
|
||||
import com.alibaba.otter.canal.protocol.Message;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.kafka.common.errors.SerializationException;
|
||||
import org.apache.kafka.common.serialization.Serializer;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import com.alibaba.otter.canal.protocol.CanalEntry;
|
||||
import com.alibaba.otter.canal.protocol.CanalPacket;
|
||||
import com.alibaba.otter.canal.protocol.CanalPacket.PacketType;
|
||||
import com.alibaba.otter.canal.protocol.Message;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.CodedOutputStream;
|
||||
import com.google.protobuf.WireFormat;
|
||||
|
||||
/**
|
||||
* Kafka Message类的序列化
|
||||
@@ -25,20 +31,53 @@ public class MessageSerializer implements Serializer<Message> {
|
||||
public byte[] serialize(String topic, Message data) {
|
||||
try {
|
||||
if (data != null) {
|
||||
CanalPacket.Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder();
|
||||
if (data.getId() != -1) {
|
||||
if (data.isRaw() && !CollectionUtils.isEmpty(data.getRawEntries())) {
|
||||
messageBuilder.addAllMessages(data.getRawEntries());
|
||||
// for performance
|
||||
List<ByteString> rowEntries = data.getRawEntries();
|
||||
// message size
|
||||
int messageSize = 0;
|
||||
messageSize += com.google.protobuf.CodedOutputStream.computeInt64Size(1, data.getId());
|
||||
|
||||
int dataSize = 0;
|
||||
for (int i = 0; i < rowEntries.size(); i++) {
|
||||
dataSize += com.google.protobuf.CodedOutputStream.computeBytesSizeNoTag(rowEntries.get(i));
|
||||
}
|
||||
messageSize += dataSize;
|
||||
messageSize += 1 * rowEntries.size();
|
||||
// packet size
|
||||
int size = 0;
|
||||
size += com.google.protobuf.CodedOutputStream.computeEnumSize(3,
|
||||
PacketType.MESSAGES.getNumber());
|
||||
size += com.google.protobuf.CodedOutputStream.computeTagSize(5)
|
||||
+ com.google.protobuf.CodedOutputStream.computeRawVarint32Size(messageSize)
|
||||
+ messageSize;
|
||||
// build data
|
||||
byte[] body = new byte[size];
|
||||
CodedOutputStream output = CodedOutputStream.newInstance(body);
|
||||
output.writeEnum(3, PacketType.MESSAGES.getNumber());
|
||||
|
||||
output.writeTag(5, WireFormat.WIRETYPE_LENGTH_DELIMITED);
|
||||
output.writeRawVarint32(messageSize);
|
||||
// message
|
||||
output.writeInt64(1, data.getId());
|
||||
for (int i = 0; i < rowEntries.size(); i++) {
|
||||
output.writeBytes(2, rowEntries.get(i));
|
||||
}
|
||||
output.checkNoSpaceLeft();
|
||||
return body;
|
||||
} else if (!CollectionUtils.isEmpty(data.getEntries())) {
|
||||
CanalPacket.Messages.Builder messageBuilder = CanalPacket.Messages.newBuilder();
|
||||
for (CanalEntry.Entry entry : data.getEntries()) {
|
||||
messageBuilder.addMessages(entry.toByteString());
|
||||
}
|
||||
|
||||
CanalPacket.Packet.Builder packetBuilder = CanalPacket.Packet.newBuilder();
|
||||
packetBuilder.setType(CanalPacket.PacketType.MESSAGES);
|
||||
packetBuilder.setBody(messageBuilder.build().toByteString());
|
||||
return packetBuilder.build().toByteArray();
|
||||
}
|
||||
}
|
||||
CanalPacket.Packet.Builder packetBuilder = CanalPacket.Packet.newBuilder();
|
||||
packetBuilder.setType(CanalPacket.PacketType.MESSAGES);
|
||||
packetBuilder.setBody(messageBuilder.build().toByteString());
|
||||
return packetBuilder.build().toByteArray();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SerializationException("Error when serializing message to byte[] ");
|
||||
|
||||
@@ -5,6 +5,7 @@ lingerMs: 1
|
||||
bufferMemory: 33554432
|
||||
# canal的批次大小,单位 k
|
||||
canalBatchSize: 50
|
||||
filterTransactionEntry: true
|
||||
|
||||
canalDestinations:
|
||||
- canalDestination: example
|
||||
|
||||
Reference in New Issue
Block a user