|
@@ -1,13 +1,17 @@
|
|
|
package com.alibaba.otter.canal.rocketmq;
|
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
|
+import java.util.stream.Collectors;
|
|
|
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
import org.apache.rocketmq.acl.common.AclClientRPCHook;
|
|
|
import org.apache.rocketmq.acl.common.SessionCredentials;
|
|
|
import org.apache.rocketmq.client.AccessChannel;
|
|
|
import org.apache.rocketmq.client.exception.MQClientException;
|
|
|
+import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
|
|
|
+import org.apache.rocketmq.client.impl.producer.TopicPublishInfo;
|
|
|
import org.apache.rocketmq.client.producer.DefaultMQProducer;
|
|
|
import org.apache.rocketmq.client.producer.MessageQueueSelector;
|
|
|
import org.apache.rocketmq.client.producer.SendResult;
|
|
@@ -133,19 +137,9 @@ public class CanalRocketMQProducer extends AbstractMQProducer implements CanalMQ
|
|
|
|
|
|
@Override
|
|
|
public void run() {
|
|
|
- try {
|
|
|
- if (logger.isDebugEnabled()) {
|
|
|
- logger.debug("flatMessagePart: {}, partition: {}",
|
|
|
- JSON.toJSONString(dataPartition, SerializerFeature.WriteMapNullValue),
|
|
|
- index);
|
|
|
- }
|
|
|
- Message data = new Message(topicName,
|
|
|
- CanalMessageSerializer.serializer(dataPartition,
|
|
|
- mqProperties.isFilterTransactionEntry()));
|
|
|
- sendMessage(data, index);
|
|
|
- } catch (Exception e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
- }
|
|
|
+ Message data = new Message(topicName, CanalMessageSerializer.serializer(dataPartition,
|
|
|
+ mqProperties.isFilterTransactionEntry()));
|
|
|
+ sendMessage(data, index);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
@@ -156,12 +150,6 @@ public class CanalRocketMQProducer extends AbstractMQProducer implements CanalMQ
|
|
|
final int partition = destination.getPartition() != null ? destination.getPartition() : 0;
|
|
|
Message data = new Message(topicName, CanalMessageSerializer.serializer(message,
|
|
|
mqProperties.isFilterTransactionEntry()));
|
|
|
- if (logger.isDebugEnabled()) {
|
|
|
- logger.debug("send message:{} to destination:{}, partition: {}",
|
|
|
- message,
|
|
|
- destination.getCanalDestination(),
|
|
|
- partition);
|
|
|
- }
|
|
|
sendMessage(data, partition);
|
|
|
}
|
|
|
} else {
|
|
@@ -170,79 +158,112 @@ public class CanalRocketMQProducer extends AbstractMQProducer implements CanalMQ
|
|
|
// 串行分区
|
|
|
List<FlatMessage> flatMessages = MQMessageUtils.messageConverter(datas, message.getId());
|
|
|
if (flatMessages != null) {
|
|
|
- for (FlatMessage flatMessage : flatMessages) {
|
|
|
- ExecutorTemplate template = new ExecutorTemplate(executor);
|
|
|
- if (destination.getPartitionHash() != null && !destination.getPartitionHash().isEmpty()) {
|
|
|
+ // 初始化分区合并队列
|
|
|
+ if (destination.getPartitionHash() != null && !destination.getPartitionHash().isEmpty()) {
|
|
|
+ List<List<FlatMessage>> partitionFlatMessages = new ArrayList<List<FlatMessage>>();
|
|
|
+ for (int i = 0; i < destination.getPartitionsNum(); i++) {
|
|
|
+ partitionFlatMessages.add(new ArrayList<FlatMessage>());
|
|
|
+ }
|
|
|
+
|
|
|
+ for (FlatMessage flatMessage : flatMessages) {
|
|
|
FlatMessage[] partitionFlatMessage = MQMessageUtils.messagePartition(flatMessage,
|
|
|
destination.getPartitionsNum(),
|
|
|
destination.getPartitionHash());
|
|
|
int length = partitionFlatMessage.length;
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
- FlatMessage flatMessagePart = partitionFlatMessage[i];
|
|
|
- if (flatMessagePart != null) {
|
|
|
- if (logger.isDebugEnabled()) {
|
|
|
- logger.debug("flatMessagePart: {}, partition: {}",
|
|
|
- JSON.toJSONString(flatMessagePart, SerializerFeature.WriteMapNullValue),
|
|
|
- i);
|
|
|
- }
|
|
|
- final int index = i;
|
|
|
- template.submit(new Runnable() {
|
|
|
-
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
- try {
|
|
|
- Message data = new Message(topicName, JSON.toJSONBytes(flatMessagePart,
|
|
|
- SerializerFeature.WriteMapNullValue));
|
|
|
- sendMessage(data, index);
|
|
|
- } catch (Exception e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
+ partitionFlatMessages.get(i).add(partitionFlatMessage[i]);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- // 批量等所有分区的结果
|
|
|
- template.waitForResult();
|
|
|
- } else {
|
|
|
- try {
|
|
|
- final int partition = destination.getPartition() != null ? destination.getPartition() : 0;
|
|
|
- if (logger.isDebugEnabled()) {
|
|
|
- logger.debug("send message: {} to topic: {} fixed partition: {}",
|
|
|
- JSON.toJSONString(flatMessage, SerializerFeature.WriteMapNullValue),
|
|
|
- topicName,
|
|
|
- partition);
|
|
|
- }
|
|
|
- Message data = new Message(topicName, JSON.toJSONBytes(flatMessage,
|
|
|
- SerializerFeature.WriteMapNullValue));
|
|
|
- sendMessage(data, partition);
|
|
|
- } catch (Exception e) {
|
|
|
- throw new RuntimeException(e);
|
|
|
+ ExecutorTemplate template = new ExecutorTemplate(executor);
|
|
|
+ for (int i = 0; i < partitionFlatMessages.size(); i++) {
|
|
|
+ final List<FlatMessage> flatMessagePart = partitionFlatMessages.get(i);
|
|
|
+ if (flatMessagePart != null) {
|
|
|
+ final int index = i;
|
|
|
+ template.submit(new Runnable() {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void run() {
|
|
|
+ List<Message> messages = flatMessagePart.stream()
|
|
|
+ .map(flatMessage -> new Message(topicName, JSON.toJSONBytes(flatMessage,
|
|
|
+ SerializerFeature.WriteMapNullValue)))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ // 批量发送
|
|
|
+ sendMessage(messages, index);
|
|
|
+ }
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ // 批量等所有分区的结果
|
|
|
+ template.waitForResult();
|
|
|
+ } else {
|
|
|
+ final int partition = destination.getPartition() != null ? destination.getPartition() : 0;
|
|
|
+ List<Message> messages = flatMessages.stream()
|
|
|
+ .map(flatMessage -> new Message(topicName, JSON.toJSONBytes(flatMessage,
|
|
|
+ SerializerFeature.WriteMapNullValue)))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ // 批量发送
|
|
|
+ sendMessage(messages, partition);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- if (logger.isDebugEnabled()) {
|
|
|
- logger.debug("send message to rocket topic: {}", destination.getTopic());
|
|
|
+ private void sendMessage(Message message, int partition) {
|
|
|
+ try {
|
|
|
+ SendResult sendResult = this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
|
|
+ if (partition > mqs.size()) {
|
|
|
+ return mqs.get(partition % mqs.size());
|
|
|
+ } else {
|
|
|
+ return mqs.get(partition);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }, null);
|
|
|
+
|
|
|
+ if (logger.isDebugEnabled()) {
|
|
|
+ logger.debug("Send Message Result: {}", sendResult);
|
|
|
+ }
|
|
|
+ } catch (Throwable e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private void sendMessage(Message message, int partition) throws Exception {
|
|
|
- SendResult sendResult = this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
|
|
+ @SuppressWarnings("deprecation")
|
|
|
+ private void sendMessage(List<Message> messages, int partition) {
|
|
|
+ if (messages.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
|
|
- if (partition > mqs.size()) {
|
|
|
- return mqs.get(partition % mqs.size());
|
|
|
- } else {
|
|
|
- return mqs.get(partition);
|
|
|
+ // 获取一下messageQueue
|
|
|
+ DefaultMQProducerImpl innerProducer = this.defaultMQProducer.getDefaultMQProducerImpl();
|
|
|
+ TopicPublishInfo topicInfo = innerProducer.getTopicPublishInfoTable().get(messages.get(0).getTopic());
|
|
|
+ if (topicInfo == null) {
|
|
|
+ for (Message message : messages) {
|
|
|
+ sendMessage(message, partition);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 批量发送
|
|
|
+ List<MessageQueue> queues = topicInfo.getMessageQueueList();
|
|
|
+ int size = queues.size();
|
|
|
+ MessageQueue queue = null;
|
|
|
+ if (partition > queues.size()) {
|
|
|
+ queue = queues.get(partition % size);
|
|
|
+ } else {
|
|
|
+ queue = queues.get(partition);
|
|
|
+ }
|
|
|
+
|
|
|
+ try {
|
|
|
+ SendResult sendResult = this.defaultMQProducer.send(messages, queue);
|
|
|
+ if (logger.isDebugEnabled()) {
|
|
|
+ logger.debug("Send Message Result: {}", sendResult);
|
|
|
}
|
|
|
+ } catch (Throwable e) {
|
|
|
+ throw new RuntimeException(e);
|
|
|
}
|
|
|
- }, null);
|
|
|
- if (logger.isDebugEnabled()) {
|
|
|
- logger.debug("Send Message Result: {}", sendResult);
|
|
|
}
|
|
|
}
|
|
|
|