mirror of
https://github.com/alibaba/canal.git
synced 2026-11-04 00:30:15 +08:00
Support seamless docking with Alibaba Cloud RocketMQ commercial service (#1849)
This commit is contained in:
@@ -3,7 +3,7 @@ package com.alibaba.otter.canal.common;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* kafka 配置项
|
||||
* MQ 配置项
|
||||
*
|
||||
* @author machengyuan 2018-6-11 下午05:30:49
|
||||
* @version 1.0.0
|
||||
@@ -27,7 +27,10 @@ public class MQProperties {
|
||||
private String aliyunSecretKey = "";
|
||||
private boolean transaction = false; // 是否开启事务
|
||||
private Properties properties = new Properties();
|
||||
|
||||
private boolean enableMessageTrace = false;
|
||||
private String accessChannel = null;
|
||||
private String customizedTraceTopic = null;
|
||||
private String namespace = "";
|
||||
public static class CanalDestination {
|
||||
|
||||
private String canalDestination;
|
||||
@@ -221,4 +224,62 @@ public class MQProperties {
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public boolean isEnableMessageTrace() {
|
||||
return enableMessageTrace;
|
||||
}
|
||||
|
||||
public void setEnableMessageTrace(boolean enableMessageTrace) {
|
||||
this.enableMessageTrace = enableMessageTrace;
|
||||
}
|
||||
|
||||
public String getAccessChannel() {
|
||||
return accessChannel;
|
||||
}
|
||||
|
||||
public void setAccessChannel(String accessChannel) {
|
||||
this.accessChannel = accessChannel;
|
||||
}
|
||||
|
||||
public String getCustomizedTraceTopic() {
|
||||
return customizedTraceTopic;
|
||||
}
|
||||
|
||||
public void setCustomizedTraceTopic(String customizedTraceTopic) {
|
||||
this.customizedTraceTopic = customizedTraceTopic;
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(String namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return "MQProperties{" +
|
||||
"servers='" + servers + '\'' +
|
||||
", retries=" + retries +
|
||||
", batchSize=" + batchSize +
|
||||
", lingerMs=" + lingerMs +
|
||||
", maxRequestSize=" + maxRequestSize +
|
||||
", bufferMemory=" + bufferMemory +
|
||||
", filterTransactionEntry=" + filterTransactionEntry +
|
||||
", producerGroup='" + producerGroup + '\'' +
|
||||
", canalBatchSize=" + canalBatchSize +
|
||||
", canalGetTimeout=" + canalGetTimeout +
|
||||
", flatMessage=" + flatMessage +
|
||||
", compressionType='" + compressionType + '\'' +
|
||||
", acks='" + acks + '\'' +
|
||||
", aliyunAccessKey='" + aliyunAccessKey + '\'' +
|
||||
", aliyunSecretKey='" + aliyunSecretKey + '\'' +
|
||||
", transaction=" + transaction +
|
||||
", properties=" + properties +
|
||||
", enableMessageTrace=" + enableMessageTrace +
|
||||
", accessChannel='" + accessChannel + '\'' +
|
||||
", customizedTraceTopic='" + customizedTraceTopic + '\'' +
|
||||
", namespace='" + namespace + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,17 +4,20 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.MQBrokerException;
|
||||
import org.apache.rocketmq.client.exception.MQClientException;
|
||||
import org.apache.rocketmq.client.producer.DefaultMQProducer;
|
||||
import org.apache.rocketmq.client.producer.MessageQueueSelector;
|
||||
import org.apache.rocketmq.client.producer.SendResult;
|
||||
import org.apache.rocketmq.common.message.Message;
|
||||
import org.apache.rocketmq.common.message.MessageQueue;
|
||||
import org.apache.rocketmq.remoting.RPCHook;
|
||||
import org.apache.rocketmq.remoting.exception.RemotingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.alibaba.otter.canal.common.CanalMessageSerializer;
|
||||
@@ -23,14 +26,13 @@ import com.alibaba.otter.canal.common.MQProperties;
|
||||
import com.alibaba.otter.canal.protocol.FlatMessage;
|
||||
import com.alibaba.otter.canal.server.exception.CanalServerException;
|
||||
import com.alibaba.otter.canal.spi.CanalMQProducer;
|
||||
import com.aliyun.openservices.apache.api.impl.authority.SessionCredentials;
|
||||
import com.aliyun.openservices.apache.api.impl.rocketmq.ClientRPCHook;
|
||||
|
||||
public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CanalRocketMQProducer.class);
|
||||
private DefaultMQProducer defaultMQProducer;
|
||||
private MQProperties mqProperties;
|
||||
private static final String CLOUD_ACCESS_CHANNEL = "cloud";
|
||||
|
||||
@Override
|
||||
public void init(MQProperties rocketMQProperties) {
|
||||
@@ -41,10 +43,16 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
SessionCredentials sessionCredentials = new SessionCredentials();
|
||||
sessionCredentials.setAccessKey(rocketMQProperties.getAliyunAccessKey());
|
||||
sessionCredentials.setSecretKey(rocketMQProperties.getAliyunSecretKey());
|
||||
rpcHook = new ClientRPCHook(sessionCredentials);
|
||||
rpcHook = new AclClientRPCHook(sessionCredentials);
|
||||
}
|
||||
|
||||
defaultMQProducer = new DefaultMQProducer(rocketMQProperties.getProducerGroup(), rpcHook);
|
||||
defaultMQProducer = new DefaultMQProducer(rocketMQProperties.getProducerGroup(), rpcHook, mqProperties.isEnableMessageTrace(), mqProperties.getCustomizedTraceTopic());
|
||||
if (CLOUD_ACCESS_CHANNEL.equals(rocketMQProperties.getAccessChannel())){
|
||||
defaultMQProducer.setAccessChannel(AccessChannel.CLOUD);
|
||||
}
|
||||
if (!StringUtils.isEmpty(mqProperties.getNamespace())){
|
||||
defaultMQProducer.setNamespace(mqProperties.getNamespace());
|
||||
}
|
||||
defaultMQProducer.setNamesrvAddr(rocketMQProperties.getServers());
|
||||
defaultMQProducer.setRetryTimesWhenSendFailed(rocketMQProperties.getRetries());
|
||||
defaultMQProducer.setVipChannelEnabled(false);
|
||||
@@ -80,6 +88,22 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
}
|
||||
}
|
||||
|
||||
private void sendMessage(Message message, int partition) throws Exception{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public void send(final MQProperties.CanalDestination destination, String topicName,
|
||||
com.alibaba.otter.canal.protocol.Message data) throws Exception {
|
||||
if (!mqProperties.getFlatMessage()) {
|
||||
@@ -102,17 +126,7 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
Message message = new Message(topicName,
|
||||
CanalMessageSerializer.serializer(dataPartition,
|
||||
mqProperties.isFilterTransactionEntry()));
|
||||
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
||||
|
||||
@Override
|
||||
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
||||
if (index > mqs.size()) {
|
||||
return mqs.get(index % mqs.size());
|
||||
} else {
|
||||
return mqs.get(index);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
sendMessage(message, index);
|
||||
} catch (Exception e) {
|
||||
logger.error("send flat message to hashed partition error", e);
|
||||
throw e;
|
||||
@@ -129,17 +143,7 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
destination.getCanalDestination(),
|
||||
partition);
|
||||
}
|
||||
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);
|
||||
sendMessage(message, partition);
|
||||
}
|
||||
} catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
|
||||
logger.error("Send message error!", e);
|
||||
@@ -166,17 +170,7 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
try {
|
||||
Message message = new Message(topicName, JSON.toJSONString(flatMessagePart,
|
||||
SerializerFeature.WriteMapNullValue).getBytes());
|
||||
this.defaultMQProducer.send(message, new MessageQueueSelector() {
|
||||
|
||||
@Override
|
||||
public MessageQueue select(List<MessageQueue> mqs, Message msg, Object arg) {
|
||||
if (index > mqs.size()) {
|
||||
return mqs.get(index % mqs.size());
|
||||
} else {
|
||||
return mqs.get(index);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
sendMessage(message, index);
|
||||
} catch (Exception e) {
|
||||
logger.error("send flat message to hashed partition error", e);
|
||||
throw e;
|
||||
@@ -194,17 +188,7 @@ public class CanalRocketMQProducer implements CanalMQProducer {
|
||||
}
|
||||
Message message = new Message(topicName, JSON.toJSONString(flatMessage,
|
||||
SerializerFeature.WriteMapNullValue).getBytes());
|
||||
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);
|
||||
sendMessage(message, partition);
|
||||
} catch (Exception e) {
|
||||
logger.error("send flat message to fixed partition error", e);
|
||||
throw e;
|
||||
|
||||
Reference in New Issue
Block a user