From c6c699ebf616c3e0199a9b71a7a441018b0e4757 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Tue, 27 Aug 2019 17:33:36 +0800
Subject: [PATCH 01/26] [RIP-16]impl rpc support
---
.../rocketmq/broker/BrokerController.java | 28 ++
.../broker/client/ProducerManager.java | 10 +
.../processor/ReplyMessageProcessor.java | 292 ++++++++++++++++++
.../processor/SendMessageProcessor.java | 6 +-
.../broker/topic/TopicConfigManager.java | 8 +
.../client/common/ClientErrorCode.java | 1 +
.../exception/RequestTimeoutException.java | 40 +++
.../client/impl/ClientRemotingProcessor.java | 88 +++++-
.../rocketmq/client/impl/MQClientAPIImpl.java | 22 +-
.../impl/producer/DefaultMQProducerImpl.java | 258 ++++++++++++++++
.../client/producer/DefaultMQProducer.java | 106 +++++++
.../rocketmq/client/producer/MQProducer.java | 22 ++
.../client/producer/RequestCallback.java | 9 +
.../client/producer/RequestFutureTable.java | 46 +++
.../producer/RequestResponseFuture.java | 117 +++++++
.../rocketmq/client/utils/MessageUtil.java | 30 ++
.../apache/rocketmq/common/BrokerConfig.java | 28 ++
.../org/apache/rocketmq/common/MixAll.java | 7 +
.../rocketmq/common/message/MessageConst.java | 14 +
.../rocketmq/common/protocol/RequestCode.java | 6 +
.../header/ReplyMessageRequestHeader.java | 153 +++++++++
.../rocketmq/common/utils/RequestIdUtil.java | 9 +
22 files changed, 1290 insertions(+), 10 deletions(-)
create mode 100644 broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
create mode 100644 client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java
create mode 100644 client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java
create mode 100644 client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java
create mode 100644 client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
create mode 100644 client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
create mode 100644 common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java
create mode 100644 common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java b/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
index a885cd0898..84b3e024ae 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
@@ -62,6 +62,7 @@ import org.apache.rocketmq.broker.processor.EndTransactionProcessor;
import org.apache.rocketmq.broker.processor.PullMessageProcessor;
import org.apache.rocketmq.broker.processor.QueryMessageProcessor;
import org.apache.rocketmq.broker.processor.SendMessageProcessor;
+import org.apache.rocketmq.broker.processor.ReplyMessageProcessor;
import org.apache.rocketmq.broker.slave.SlaveSynchronize;
import org.apache.rocketmq.broker.subscription.SubscriptionGroupManager;
import org.apache.rocketmq.broker.topic.TopicConfigManager;
@@ -132,6 +133,7 @@ public class BrokerController {
private final SlaveSynchronize slaveSynchronize;
private final BlockingQueue sendThreadPoolQueue;
private final BlockingQueue pullThreadPoolQueue;
+ private final BlockingQueue replyThreadPoolQueue;
private final BlockingQueue queryThreadPoolQueue;
private final BlockingQueue clientManagerThreadPoolQueue;
private final BlockingQueue heartbeatThreadPoolQueue;
@@ -147,6 +149,7 @@ public class BrokerController {
private TopicConfigManager topicConfigManager;
private ExecutorService sendMessageExecutor;
private ExecutorService pullMessageExecutor;
+ private ExecutorService replyMessageExecutor;
private ExecutorService queryMessageExecutor;
private ExecutorService adminBrokerExecutor;
private ExecutorService clientManageExecutor;
@@ -194,6 +197,7 @@ public class BrokerController {
this.sendThreadPoolQueue = new LinkedBlockingQueue(this.brokerConfig.getSendThreadPoolQueueCapacity());
this.pullThreadPoolQueue = new LinkedBlockingQueue(this.brokerConfig.getPullThreadPoolQueueCapacity());
+ this.replyThreadPoolQueue = new LinkedBlockingQueue(this.brokerConfig.getReplyThreadPoolQueueCapacity());
this.queryThreadPoolQueue = new LinkedBlockingQueue(this.brokerConfig.getQueryThreadPoolQueueCapacity());
this.clientManagerThreadPoolQueue = new LinkedBlockingQueue(this.brokerConfig.getClientManagerThreadPoolQueueCapacity());
this.consumerManagerThreadPoolQueue = new LinkedBlockingQueue(this.brokerConfig.getConsumerManagerThreadPoolQueueCapacity());
@@ -277,6 +281,14 @@ public class BrokerController {
this.pullThreadPoolQueue,
new ThreadFactoryImpl("PullMessageThread_"));
+ this.replyMessageExecutor = new BrokerFixedThreadPoolExecutor(
+ this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
+ this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.replyThreadPoolQueue,
+ new ThreadFactoryImpl("ProcessReplyMessageThread_"));
+
this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getQueryMessageThreadPoolNums(),
this.brokerConfig.getQueryMessageThreadPoolNums(),
@@ -553,6 +565,18 @@ public class BrokerController {
this.remotingServer.registerProcessor(RequestCode.PULL_MESSAGE, this.pullMessageProcessor, this.pullMessageExecutor);
this.pullMessageProcessor.registerConsumeMessageHook(consumeMessageHookList);
+ /**
+ * ReplyMessageProcessor
+ */
+ ReplyMessageProcessor replyMessageProcessor = new ReplyMessageProcessor(this);
+ replyMessageProcessor.registerSendMessageHook(sendMessageHookList);
+
+ this.remotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE, replyMessageProcessor, replyMessageExecutor);
+ this.remotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE_V2, replyMessageProcessor, replyMessageExecutor);
+ this.fastRemotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE, replyMessageProcessor, replyMessageExecutor);
+ this.fastRemotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE_V2, replyMessageProcessor, replyMessageExecutor);
+
+
/**
* QueryMessageProcessor
*/
@@ -763,6 +787,10 @@ public class BrokerController {
this.pullMessageExecutor.shutdown();
}
+ if (this.replyMessageExecutor != null) {
+ this.replyMessageExecutor.shutdown();
+ }
+
if (this.adminBrokerExecutor != null) {
this.adminBrokerExecutor.shutdown();
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
index 61ceae5386..db372fa8c8 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
@@ -24,6 +24,7 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
@@ -43,6 +44,7 @@ public class ProducerManager {
private final Lock groupChannelLock = new ReentrantLock();
private final HashMap> groupChannelTable =
new HashMap>();
+ private final ConcurrentHashMap clientChannelTable = new ConcurrentHashMap<>();
private PositiveAtomicCounter positiveAtomicCounter = new PositiveAtomicCounter();
public ProducerManager() {
}
@@ -82,6 +84,7 @@ public class ProducerManager {
long diff = System.currentTimeMillis() - info.getLastUpdateTimestamp();
if (diff > CHANNEL_EXPIRED_TIMEOUT) {
it.remove();
+ clientChannelTable.remove(info.getClientId());
log.warn(
"SCAN: remove expired channel[{}] from ProducerManager groupChannelTable, producer group name: {}",
RemotingHelper.parseChannelRemoteAddr(info.getChannel()), group);
@@ -113,6 +116,7 @@ public class ProducerManager {
final ClientChannelInfo clientChannelInfo =
clientChannelInfoTable.remove(channel);
if (clientChannelInfo != null) {
+ clientChannelTable.remove(clientChannelInfo.getClientId());
log.info(
"NETTY EVENT: remove channel[{}][{}] from ProducerManager groupChannelTable, producer group: {}",
clientChannelInfo.toString(), remoteAddr, group);
@@ -146,6 +150,7 @@ public class ProducerManager {
clientChannelInfoFound = channelTable.get(clientChannelInfo.getChannel());
if (null == clientChannelInfoFound) {
channelTable.put(clientChannelInfo.getChannel(), clientChannelInfo);
+ clientChannelTable.put(clientChannelInfo.getClientId(), clientChannelInfo.getChannel());
log.info("new producer connected, group: {} channel: {}", group,
clientChannelInfo.toString());
}
@@ -171,6 +176,7 @@ public class ProducerManager {
HashMap channelTable = this.groupChannelTable.get(group);
if (null != channelTable && !channelTable.isEmpty()) {
ClientChannelInfo old = channelTable.remove(clientChannelInfo.getChannel());
+ clientChannelTable.remove(clientChannelInfo.getClientId());
if (old != null) {
log.info("unregister a producer[{}] from groupChannelTable {}", group,
clientChannelInfo.toString());
@@ -223,4 +229,8 @@ public class ProducerManager {
}
return null;
}
+
+ public Channel findChannel(String clientId) {
+ return clientChannelTable.get(clientId);
+ }
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
new file mode 100644
index 0000000000..00960d7990
--- /dev/null
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
@@ -0,0 +1,292 @@
+package org.apache.rocketmq.broker.processor;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.mqtrace.SendMessageContext;
+import org.apache.rocketmq.common.*;
+import org.apache.rocketmq.common.message.*;
+import org.apache.rocketmq.common.protocol.RequestCode;
+import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.ReplyMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeaderV2;
+import org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader;
+import org.apache.rocketmq.remoting.exception.RemotingCommandException;
+import org.apache.rocketmq.remoting.exception.RemotingException;
+import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import org.apache.rocketmq.store.*;
+import org.apache.rocketmq.store.stats.BrokerStatsManager;
+
+public class ReplyMessageProcessor extends AbstractSendMessageProcessor implements NettyRequestProcessor {
+
+ public ReplyMessageProcessor(final BrokerController brokerController) {
+ super(brokerController);
+ }
+
+ @Override
+ public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
+ SendMessageContext mqtraceContext = null;
+ SendMessageRequestHeader requestHeader = parseRequestHeader(request);
+ if (requestHeader == null) {
+ return null;
+ }
+
+ mqtraceContext = buildMsgContext(ctx, requestHeader);
+ this.executeSendMessageHookBefore(ctx, request, mqtraceContext);
+
+ RemotingCommand response = this.processReplyMessageRequest(ctx, request, mqtraceContext, requestHeader);
+
+ this.executeSendMessageHookAfter(response, mqtraceContext);
+ return response;
+ }
+
+ @Override
+ protected SendMessageRequestHeader parseRequestHeader(RemotingCommand request) throws RemotingCommandException {
+ SendMessageRequestHeaderV2 requestHeaderV2 = null;
+ SendMessageRequestHeader requestHeader = null;
+ switch (request.getCode()) {
+ case RequestCode.SEND_REPLY_MESSAGE_V2:
+ requestHeaderV2 =
+ (SendMessageRequestHeaderV2) request
+ .decodeCommandCustomHeader(SendMessageRequestHeaderV2.class);
+ case RequestCode.SEND_REPLY_MESSAGE:
+ if (null == requestHeaderV2) {
+ requestHeader =
+ (SendMessageRequestHeader) request
+ .decodeCommandCustomHeader(SendMessageRequestHeader.class);
+ } else {
+ requestHeader = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV1(requestHeaderV2);
+ }
+ default:
+ break;
+ }
+ return requestHeader;
+ }
+
+ private RemotingCommand processReplyMessageRequest(final ChannelHandlerContext ctx,
+ final RemotingCommand request,
+ final SendMessageContext sendMessageContext,
+ final SendMessageRequestHeader requestHeader) {
+ final RemotingCommand response = RemotingCommand.createResponseCommand(SendMessageResponseHeader.class);
+ final SendMessageResponseHeader responseHeader = (SendMessageResponseHeader)response.readCustomHeader();
+
+ response.setOpaque(request.getOpaque());
+
+ response.addExtField(MessageConst.PROPERTY_MSG_REGION, this.brokerController.getBrokerConfig().getRegionId());
+ response.addExtField(MessageConst.PROPERTY_TRACE_SWITCH, String.valueOf(this.brokerController.getBrokerConfig().isTraceOn()));
+
+ log.debug("receive SendReplyMessage request command, {}", request);
+ final long startTimstamp = this.brokerController.getBrokerConfig().getStartAcceptSendRequestTimeStamp();
+ if (this.brokerController.getMessageStore().now() < startTimstamp) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark(String.format("broker unable to service, until %s", UtilAll.timeMillisToHumanString2(startTimstamp)));
+ return response;
+ }
+
+ response.setCode(-1);
+ super.msgCheck(ctx, requestHeader, response);
+ if (response.getCode() != -1) {
+ return response;
+ }
+
+ final byte[] body = request.getBody();
+
+ int queueIdInt = requestHeader.getQueueId();
+ TopicConfig topicConfig = this.brokerController.getTopicConfigManager().selectTopicConfig(requestHeader.getTopic());
+
+ if (queueIdInt < 0) {
+ queueIdInt = Math.abs(this.random.nextInt() % 99999999) % topicConfig.getWriteQueueNums();
+ }
+
+ MessageExtBrokerInner msgInner = new MessageExtBrokerInner();
+ msgInner.setTopic(requestHeader.getTopic());
+ msgInner.setQueueId(queueIdInt);
+ msgInner.setBody(body);
+ msgInner.setFlag(requestHeader.getFlag());
+ MessageAccessor.setProperties(msgInner, MessageDecoder.string2messageProperties(requestHeader.getProperties()));
+ msgInner.setPropertiesString(requestHeader.getProperties());
+ msgInner.setBornTimestamp(requestHeader.getBornTimestamp());
+ msgInner.setBornHost(ctx.channel().remoteAddress());
+ msgInner.setStoreHost(this.getStoreHost());
+ msgInner.setReconsumeTimes(requestHeader.getReconsumeTimes() == null ? 0 : requestHeader.getReconsumeTimes());
+
+ boolean pushOk = this.pushReplyMessage(ctx, requestHeader, msgInner, response);
+
+ if (pushOk && this.brokerController.getBrokerConfig().isStoreReplyMessageEnable()) {
+ PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
+ this.handlePutMessageResult(putMessageResult, response, request, msgInner, responseHeader, sendMessageContext, ctx, queueIdInt);
+ } else {
+ responseHeader.setMsgId("0");
+ responseHeader.setQueueId(0);
+ responseHeader.setQueueOffset(0L);
+ }
+
+ return response;
+ }
+
+ private boolean pushReplyMessage(final ChannelHandlerContext ctx, final SendMessageRequestHeader requestHeader, final Message msg, final RemotingCommand response) {
+ ReplyMessageRequestHeader replyMessageRequestHeader = new ReplyMessageRequestHeader();
+ replyMessageRequestHeader.setBornHost(ctx.channel().remoteAddress().toString());
+ replyMessageRequestHeader.setStoreHost(this.getStoreHost().toString());
+ replyMessageRequestHeader.setStoreTimestamp(System.currentTimeMillis());
+ replyMessageRequestHeader.setProducerGroup(requestHeader.getProducerGroup());
+ replyMessageRequestHeader.setTopic(requestHeader.getTopic());
+ replyMessageRequestHeader.setDefaultTopic(requestHeader.getDefaultTopic());
+ replyMessageRequestHeader.setDefaultTopicQueueNums(requestHeader.getDefaultTopicQueueNums());
+ replyMessageRequestHeader.setQueueId(requestHeader.getQueueId());
+ replyMessageRequestHeader.setSysFlag(requestHeader.getSysFlag());
+ replyMessageRequestHeader.setBornTimestamp(requestHeader.getBornTimestamp());
+ replyMessageRequestHeader.setFlag(requestHeader.getFlag());
+ replyMessageRequestHeader.setProperties(requestHeader.getProperties());
+ replyMessageRequestHeader.setReconsumeTimes(requestHeader.getReconsumeTimes());
+ replyMessageRequestHeader.setUnitMode(requestHeader.isUnitMode());
+
+ RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.PUSH_REPLY_MESSAGE_TO_CLIENT, replyMessageRequestHeader);
+ request.setBody(msg.getBody());
+
+ String senderId = msg.getProperties().get(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
+ boolean pushOk = false;
+
+ if (senderId != null) {
+ Channel channel = this.brokerController.getProducerManager().findChannel(senderId);
+ if (channel != null) {
+ msg.getProperties().put(MessageConst.PROPERTY_PUSH_REPLY_TIME, String.valueOf(System.currentTimeMillis()));
+ replyMessageRequestHeader.setProperties(MessageDecoder.messageProperties2String(msg.getProperties()));
+
+ try {
+ RemotingCommand pushResponse = this.brokerController.getBroker2Client().callClient(channel, request);
+ assert pushResponse != null;
+ switch (pushResponse.getCode()) {
+ case ResponseCode.SUCCESS: {
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ pushOk = true;
+ break;
+ }
+ default: {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("push reply message to requester fail");
+ log.warn("push reply message to <{}> return fail, remark: {}", senderId, response.getRemark());
+ }
+ }
+ } catch (InterruptedException e) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("push reply message to requester fail");
+ log.warn("push reply message to <{}> fail. {}", senderId, channel, e);
+ } catch (RemotingException e) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("push reply message to requester fail");
+ log.warn("push reply message to <{}> fail. {}", senderId, channel, e);
+ }
+ } else {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("channel of <" + senderId + "> not found");
+ log.warn("push reply message fial, channel of <{}> not found.", senderId);
+ }
+ return pushOk;
+ }
+ log.warn("REPLY_TO is null, can not reply message");
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("REPLY_TO is null");
+ return pushOk;
+ }
+
+ private void handlePutMessageResult(PutMessageResult putMessageResult, final RemotingCommand response,
+ final RemotingCommand request, final MessageExt msg,
+ final SendMessageResponseHeader responseHeader, SendMessageContext sendMessageContext, ChannelHandlerContext ctx,
+ int queueIdInt) {
+ if (putMessageResult == null) {
+ response.setRemark("push reply to requester success, but store putMessage return null");
+ return ;
+ }
+ boolean sendOK = false;
+
+ switch (putMessageResult.getPutMessageStatus()) {
+ // Success
+ case PUT_OK:
+ sendOK = true;
+ response.setCode(ResponseCode.SUCCESS);
+ break;
+ case FLUSH_DISK_TIMEOUT:
+ response.setCode(ResponseCode.FLUSH_DISK_TIMEOUT);
+ sendOK = true;
+ break;
+ case FLUSH_SLAVE_TIMEOUT:
+ response.setCode(ResponseCode.FLUSH_SLAVE_TIMEOUT);
+ sendOK = true;
+ break;
+ case SLAVE_NOT_AVAILABLE:
+ response.setCode(ResponseCode.SLAVE_NOT_AVAILABLE);
+ sendOK = true;
+ break;
+
+ // Failed
+ case CREATE_MAPEDFILE_FAILED:
+// response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("create mapped file failed, server is busy or broken.");
+ break;
+ case MESSAGE_ILLEGAL:
+ case PROPERTIES_SIZE_EXCEEDED:
+// response.setCode(ResponseCode.MESSAGE_ILLEGAL);
+ response.setRemark(
+ "the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k, msg properties length limit 32k.");
+ break;
+ case SERVICE_NOT_AVAILABLE:
+// response.setCode(ResponseCode.SERVICE_NOT_AVAILABLE);
+ response.setRemark(
+ "service not available now, maybe disk full, maybe your broker machine memory too small.");
+ break;
+ case OS_PAGECACHE_BUSY:
+// response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("[PC_SYNCHRONIZED]broker busy, start flow control for a while");
+ break;
+ case UNKNOWN_ERROR:
+// response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("UNKNOWN_ERROR");
+ break;
+ default:
+// response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("UNKNOWN_ERROR DEFAULT");
+ break;
+ }
+
+ String owner = request.getExtFields().get(BrokerStatsManager.COMMERCIAL_OWNER);
+ if (sendOK) {
+ this.brokerController.getBrokerStatsManager().incTopicPutNums(msg.getTopic(), putMessageResult.getAppendMessageResult().getMsgNum(), 1);
+ this.brokerController.getBrokerStatsManager().incTopicPutSize(msg.getTopic(),
+ putMessageResult.getAppendMessageResult().getWroteBytes());
+ this.brokerController.getBrokerStatsManager().incBrokerPutNums(putMessageResult.getAppendMessageResult().getMsgNum());
+ response.setRemark(null);
+ responseHeader.setMsgId(putMessageResult.getAppendMessageResult().getMsgId());
+ responseHeader.setQueueId(queueIdInt);
+ responseHeader.setQueueOffset(putMessageResult.getAppendMessageResult().getLogicsOffset());
+
+ if (hasSendMessageHook()) {
+ sendMessageContext.setMsgId(responseHeader.getMsgId());
+ sendMessageContext.setQueueId(responseHeader.getQueueId());
+ sendMessageContext.setQueueOffset(responseHeader.getQueueOffset());
+
+ int commercialBaseCount = brokerController.getBrokerConfig().getCommercialBaseCount();
+ int wroteSize = putMessageResult.getAppendMessageResult().getWroteBytes();
+ int incValue = (int)Math.ceil(wroteSize / BrokerStatsManager.SIZE_PER_COUNT) * commercialBaseCount;
+
+ sendMessageContext.setCommercialSendStats(BrokerStatsManager.StatsType.SEND_SUCCESS);
+ sendMessageContext.setCommercialSendTimes(incValue);
+ sendMessageContext.setCommercialSendSize(wroteSize);
+ sendMessageContext.setCommercialOwner(owner);
+ }
+ } else {
+ if (hasSendMessageHook()) {
+ int wroteSize = request.getBody().length;
+ int incValue = (int)Math.ceil(wroteSize / BrokerStatsManager.SIZE_PER_COUNT);
+
+ sendMessageContext.setCommercialSendStats(BrokerStatsManager.StatsType.SEND_FAILURE);
+ sendMessageContext.setCommercialSendTimes(incValue);
+ sendMessageContext.setCommercialSendSize(wroteSize);
+ sendMessageContext.setCommercialOwner(owner);
+ }
+ }
+ }
+}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java
index 8035ae6f18..2589a7547d 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/SendMessageProcessor.java
@@ -343,11 +343,13 @@ public class SendMessageProcessor extends AbstractSendMessageProcessor implement
msgInner.setBody(body);
msgInner.setFlag(requestHeader.getFlag());
MessageAccessor.setProperties(msgInner, MessageDecoder.string2messageProperties(requestHeader.getProperties()));
- msgInner.setPropertiesString(requestHeader.getProperties());
msgInner.setBornTimestamp(requestHeader.getBornTimestamp());
msgInner.setBornHost(ctx.channel().remoteAddress());
msgInner.setStoreHost(this.getStoreHost());
msgInner.setReconsumeTimes(requestHeader.getReconsumeTimes() == null ? 0 : requestHeader.getReconsumeTimes());
+ String clusterName = this.brokerController.getBrokerConfig().getBrokerClusterName();
+ MessageAccessor.putProperty(msgInner, MessageConst.PROPERTY_CLUSTER, clusterName);
+ msgInner.setPropertiesString(MessageDecoder.messageProperties2String(msgInner.getProperties()));
PutMessageResult putMessageResult = null;
Map oriProps = MessageDecoder.string2messageProperties(requestHeader.getProperties());
String traFlag = oriProps.get(MessageConst.PROPERTY_TRANSACTION_PREPARED);
@@ -536,6 +538,8 @@ public class SendMessageProcessor extends AbstractSendMessageProcessor implement
messageExtBatch.setBornHost(ctx.channel().remoteAddress());
messageExtBatch.setStoreHost(this.getStoreHost());
messageExtBatch.setReconsumeTimes(requestHeader.getReconsumeTimes() == null ? 0 : requestHeader.getReconsumeTimes());
+ String clusterName = this.brokerController.getBrokerConfig().getBrokerClusterName();
+ MessageAccessor.putProperty(messageExtBatch, MessageConst.PROPERTY_CLUSTER, clusterName);
PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessages(messageExtBatch);
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
index 8f215cdcb9..577fff57ee 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
@@ -134,6 +134,14 @@ public class TopicConfigManager extends ConfigManager {
this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
}
}
+ {
+ String topic = this.brokerController.getBrokerConfig().getBrokerClusterName() + "_" + MixAll.REPLY_TOPIC_POSTFIX;
+ TopicConfig topicConfig = new TopicConfig(topic);
+ this.systemTopicList.add(topic);
+ topicConfig.setReadQueueNums(1);
+ topicConfig.setWriteQueueNums(1);
+ this.topicConfigTable.put(topicConfig.getTopicName(), topicConfig);
+ }
}
public boolean isSystemTopic(final String topic) {
diff --git a/client/src/main/java/org/apache/rocketmq/client/common/ClientErrorCode.java b/client/src/main/java/org/apache/rocketmq/client/common/ClientErrorCode.java
index 62a95dfa5a..633670aecc 100644
--- a/client/src/main/java/org/apache/rocketmq/client/common/ClientErrorCode.java
+++ b/client/src/main/java/org/apache/rocketmq/client/common/ClientErrorCode.java
@@ -23,4 +23,5 @@ public class ClientErrorCode {
public static final int BROKER_NOT_EXIST_EXCEPTION = 10003;
public static final int NO_NAME_SERVER_EXCEPTION = 10004;
public static final int NOT_FOUND_TOPIC_EXCEPTION = 10005;
+ public static final int REQUEST_TIMEOUT_EXCEPTION = 10006;
}
\ No newline at end of file
diff --git a/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java b/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java
new file mode 100644
index 0000000000..fd338d6004
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java
@@ -0,0 +1,40 @@
+package org.apache.rocketmq.client.exception;
+
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.help.FAQUrl;
+
+public class RequestTimeoutException extends Exception {
+ private static final long serialVersionUID = -5758410930844185841L;
+ private int responseCode;
+ private String errorMessage;
+
+ public RequestTimeoutException(String errorMessage, Throwable cause) {
+ super(errorMessage, cause);
+ this.responseCode = -1;
+ this.errorMessage = errorMessage;
+ }
+
+ public RequestTimeoutException(int responseCode, String errorMessage) {
+ super("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: "
+ + errorMessage);
+ this.responseCode = responseCode;
+ this.errorMessage = errorMessage;
+ }
+
+ public int getResponseCode() {
+ return responseCode;
+ }
+
+ public RequestTimeoutException setResponseCode(final int responseCode) {
+ this.responseCode = responseCode;
+ return this;
+ }
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(final String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
index 0bd810a1e1..7a17a04307 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
@@ -16,6 +16,8 @@
*/
package org.apache.rocketmq.client.impl;
+import java.io.IOException;
+import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
@@ -25,11 +27,10 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.client.impl.producer.MQProducerInner;
import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.RequestFutureTable;
+import org.apache.rocketmq.client.producer.RequestResponseFuture;
import org.apache.rocketmq.common.UtilAll;
-import org.apache.rocketmq.common.message.MessageConst;
-import org.apache.rocketmq.common.message.MessageDecoder;
-import org.apache.rocketmq.common.message.MessageExt;
-import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.message.*;
import org.apache.rocketmq.common.protocol.NamespaceUtil;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
@@ -43,6 +44,8 @@ import org.apache.rocketmq.common.protocol.header.GetConsumerRunningInfoRequestH
import org.apache.rocketmq.common.protocol.header.GetConsumerStatusRequestHeader;
import org.apache.rocketmq.common.protocol.header.NotifyConsumerIdsChangedRequestHeader;
import org.apache.rocketmq.common.protocol.header.ResetOffsetRequestHeader;
+import org.apache.rocketmq.common.protocol.header.ReplyMessageRequestHeader;
+import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
@@ -76,6 +79,9 @@ public class ClientRemotingProcessor implements NettyRequestProcessor {
case RequestCode.CONSUME_MESSAGE_DIRECTLY:
return this.consumeMessageDirectly(ctx, request);
+
+ case RequestCode.PUSH_REPLY_MESSAGE_TO_CLIENT:
+ return this.receiveReplyMssage(ctx, request);
default:
break;
}
@@ -213,4 +219,78 @@ public class ClientRemotingProcessor implements NettyRequestProcessor {
return response;
}
+
+ private RemotingCommand receiveReplyMssage(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
+
+ final RemotingCommand response = RemotingCommand.createResponseCommand(null);
+ long receiveTime = System.currentTimeMillis();
+ ReplyMessageRequestHeader requestHeader = (ReplyMessageRequestHeader) request.decodeCommandCustomHeader(ReplyMessageRequestHeader.class);
+
+ try {
+ MessageExt msg = new MessageExt();
+ msg.setTopic(requestHeader.getTopic());
+ msg.setQueueId(requestHeader.getQueueId());
+ msg.setStoreTimestamp(requestHeader.getStoreTimestamp());
+
+ if (requestHeader.getBornHost() != null) {
+ String[] bornHostArr = requestHeader.getBornHost().split("/");
+ String bornHost/*ip:port*/ = bornHostArr[bornHostArr.length - 1];
+ String[] host = bornHost.split(":");
+ if (host.length == 2)
+ msg.setBornHost(new InetSocketAddress(host[0], Integer.parseInt(host[1])));
+ }
+
+ if (requestHeader.getStoreHost() != null) {
+ String[] storeHostArr = requestHeader.getStoreHost().split("/");
+ String storeHost = storeHostArr[storeHostArr.length - 1];
+ String[] host = storeHost.split(":");
+ if (host.length == 2)
+ msg.setStoreHost(new InetSocketAddress(host[0], Integer.parseInt(host[1])));
+ }
+
+ byte[] body = request.getBody();
+ if ((requestHeader.getSysFlag() & MessageSysFlag.COMPRESSED_FLAG) == MessageSysFlag.COMPRESSED_FLAG) {
+ try {
+ body = UtilAll.uncompress(body);
+ } catch (IOException e) {
+ log.warn("err when uncompress constant", e);
+ }
+ }
+ msg.setBody(body);
+ msg.setFlag(requestHeader.getFlag());
+ MessageAccessor.setProperties(msg, MessageDecoder.string2messageProperties(requestHeader.getProperties()));
+ MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REPLY_MESSAGE_ARRIVE_TIME, String.valueOf(receiveTime));
+ msg.setBornTimestamp(requestHeader.getBornTimestamp());
+ msg.setReconsumeTimes(requestHeader.getReconsumeTimes() == null ? 0 : requestHeader.getReconsumeTimes());
+ log.debug("receive reply message :{}", msg);
+
+ processReplyMessage(msg);
+ } catch (Exception e) {
+ log.warn("unknown err when receiveRRReplyMsg", e);
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark("process reply message fail");
+ }
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ return response;
+ }
+
+ private void processReplyMessage(MessageExt replyMsg) {
+ final String uniqueId = replyMsg.getUserProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+ final RequestResponseFuture requestResponseFuture = RequestFutureTable.getRequestFutureTable().get(uniqueId);
+ if (requestResponseFuture != null) {
+ requestResponseFuture.putResponseMessage(replyMsg);
+
+ RequestFutureTable.getRequestFutureTable().remove(uniqueId);
+
+ if (requestResponseFuture.getRequestCallback() != null) {
+ requestResponseFuture.getRequestCallback().onSuccess(replyMsg);
+ } else {
+ requestResponseFuture.putResponseMessage(replyMsg);
+ }
+ } else {
+ log.warn(String.format("receive reply message, but not matched any request, REQUEST_UNIQ_ID: %s", uniqueId));
+ }
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
index b743af93d4..f780adf9de 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
@@ -199,6 +199,8 @@ public class MQClientAPIImpl {
this.remotingClient.registerProcessor(RequestCode.GET_CONSUMER_RUNNING_INFO, this.clientRemotingProcessor, null);
this.remotingClient.registerProcessor(RequestCode.CONSUME_MESSAGE_DIRECTLY, this.clientRemotingProcessor, null);
+
+ this.remotingClient.registerProcessor(RequestCode.PUSH_REPLY_MESSAGE_TO_CLIENT, this.clientRemotingProcessor, null);
}
public List getNameServerAddressList() {
@@ -419,13 +421,23 @@ public class MQClientAPIImpl {
) throws RemotingException, MQBrokerException, InterruptedException {
long beginStartTime = System.currentTimeMillis();
RemotingCommand request = null;
- if (sendSmartMsg || msg instanceof MessageBatch) {
- SendMessageRequestHeaderV2 requestHeaderV2 = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(requestHeader);
- request = RemotingCommand.createRequestCommand(msg instanceof MessageBatch ? RequestCode.SEND_BATCH_MESSAGE : RequestCode.SEND_MESSAGE_V2, requestHeaderV2);
+ String msgType = msg.getProperty(MessageConst.PROPERTY_MESSAGE_TYPE);
+ boolean isReply = msgType != null && msgType.equals(MixAll.REPLY_MESSAGE_FLAG);
+ if (isReply) {
+ if (sendSmartMsg) {
+ SendMessageRequestHeaderV2 requestHeaderV2 = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(requestHeader);
+ request = RemotingCommand.createRequestCommand(RequestCode.SEND_REPLY_MESSAGE_V2, requestHeaderV2);
+ } else {
+ request = RemotingCommand.createRequestCommand(RequestCode.SEND_REPLY_MESSAGE, requestHeader);
+ }
} else {
- request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, requestHeader);
+ if (sendSmartMsg || msg instanceof MessageBatch) {
+ SendMessageRequestHeaderV2 requestHeaderV2 = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV2(requestHeader);
+ request = RemotingCommand.createRequestCommand(msg instanceof MessageBatch ? RequestCode.SEND_BATCH_MESSAGE : RequestCode.SEND_MESSAGE_V2, requestHeaderV2);
+ } else {
+ request = RemotingCommand.createRequestCommand(RequestCode.SEND_MESSAGE, requestHeader);
+ }
}
-
request.setBody(msg.getBody());
switch (communicationMode) {
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
index 62aaef3b13..7a0bc4cd98 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
@@ -24,6 +24,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -39,6 +41,7 @@ import org.apache.rocketmq.client.Validators;
import org.apache.rocketmq.client.common.ClientErrorCode;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.exception.RequestTimeoutException;
import org.apache.rocketmq.client.hook.CheckForbiddenContext;
import org.apache.rocketmq.client.hook.CheckForbiddenHook;
import org.apache.rocketmq.client.hook.SendMessageContext;
@@ -52,6 +55,9 @@ import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.LocalTransactionExecuter;
import org.apache.rocketmq.client.producer.LocalTransactionState;
import org.apache.rocketmq.client.producer.MessageQueueSelector;
+import org.apache.rocketmq.client.producer.RequestCallback;
+import org.apache.rocketmq.client.producer.RequestFutureTable;
+import org.apache.rocketmq.client.producer.RequestResponseFuture;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.producer.SendStatus;
@@ -79,11 +85,13 @@ import org.apache.rocketmq.common.protocol.header.CheckTransactionStateRequestHe
import org.apache.rocketmq.common.protocol.header.EndTransactionRequestHeader;
import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
+import org.apache.rocketmq.common.utils.RequestIdUtil;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingConnectException;
import org.apache.rocketmq.remoting.exception.RemotingException;
+import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
import org.apache.rocketmq.remoting.exception.RemotingTooMuchRequestException;
@@ -107,6 +115,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
private final BlockingQueue asyncSenderThreadPoolQueue;
private final ExecutorService defaultAsyncSenderExecutor;
private ExecutorService asyncSenderExecutor;
+ private final Timer timer = new Timer("RequestHouseKeepingService", true);
public DefaultMQProducerImpl(final DefaultMQProducer defaultMQProducer) {
this(defaultMQProducer, null);
@@ -212,6 +221,17 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
this.mQClientFactory.sendHeartbeatToAllBrokerWithLock();
+
+ this.timer.scheduleAtFixedRate(new TimerTask() {
+ @Override
+ public void run() {
+ try {
+ RequestFutureTable.scanExpiredRequest();
+ } catch (Throwable e) {
+ log.error("scan RequestFutureTable exception", e);
+ }
+ }
+ }, 1000 * 3, 1000);
}
private void checkConfig() throws MQClientException {
@@ -1310,6 +1330,244 @@ public class DefaultMQProducerImpl implements MQProducerInner {
return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null, timeout);
}
+ public Message request(Message msg, long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException {
+ prepareSendRequest(msg, timeout);
+ final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+
+ try {
+ final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null);
+ RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+
+ this.sendDefaultImpl(msg, CommunicationMode.ASYNC, new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ requestResponseFuture.setSendReqeustOk(true);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ requestResponseFuture.setSendReqeustOk(false);
+ requestResponseFuture.putResponseMessage(null);
+ requestResponseFuture.setCause(e);
+ }
+ }, timeout);
+
+ Message responseMessage = requestResponseFuture.waitResponseMessage(timeout);
+ if (responseMessage == null) {
+ if (requestResponseFuture.isSendReqeustOk()) {
+ throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
+ "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
+ } else {
+ throw new MQClientException("send request message to <" + msg.getTopic() + "> fail", requestResponseFuture.getCause());
+ }
+ }
+ return responseMessage;
+ } finally {
+ RequestFutureTable.getRequestFutureTable().remove(requestUniqId);
+ }
+ }
+
+ public void request(Message msg, final RequestCallback requestCallback, long timeout) throws RemotingException {
+ prepareSendRequest(msg, timeout);
+ final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+
+ try {
+ final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback);
+ RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+
+ this.sendDefaultImpl(msg, CommunicationMode.ASYNC, new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ requestResponseFuture.setSendReqeustOk(true);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ requestResponseFuture.setCause(e);
+ requestFail(requestUniqId);
+ }
+ }, timeout);
+ } catch (Exception ex) {
+ log.warn("send request message to <{}> failed.", msg.getTopic(), ex);
+ throw new RemotingSendRequestException(msg.getTopic(), ex);
+ }
+ }
+
+ public Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final long timeout) throws MQClientException, RemotingException, MQBrokerException,
+ InterruptedException, RequestTimeoutException {
+ prepareSendRequest(msg, timeout);
+ final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+
+ try {
+ final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null);
+ RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+
+ this.sendSelectImpl(msg, selector, arg, CommunicationMode.ASYNC, new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ requestResponseFuture.setSendReqeustOk(true);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ requestResponseFuture.setSendReqeustOk(false);
+ requestResponseFuture.putResponseMessage(null);
+ requestResponseFuture.setCause(e);
+ }
+ }, timeout);
+
+ Message responseMessage = requestResponseFuture.waitResponseMessage(timeout);
+ if (responseMessage == null) {
+ if (requestResponseFuture.isSendReqeustOk()) {
+ throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
+ "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
+ } else {
+ throw new MQClientException("send request message to <" + msg.getTopic() + "> fail", requestResponseFuture.getCause());
+ }
+ }
+ return responseMessage;
+ } finally {
+ RequestFutureTable.getRequestFutureTable().remove(requestUniqId);
+ }
+ }
+
+ public void request(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final RequestCallback requestCallback, final long timeout) throws RemotingException {
+ prepareSendRequest(msg, timeout);
+ final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+
+ try {
+ final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback);
+ RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+
+ this.sendSelectImpl(msg, selector, arg, CommunicationMode.ASYNC, new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ requestResponseFuture.setSendReqeustOk(true);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ requestResponseFuture.setCause(e);
+ requestFail(requestUniqId);
+ }
+ }, timeout);
+ } catch (Exception ex) {
+ log.warn("send request message to <{}> failed.", msg.getTopic(), ex);
+ throw new RemotingSendRequestException(msg.getTopic(), ex);
+ }
+ }
+
+ public Message request(final Message msg, final MessageQueue mq, final long timeout)
+ throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
+ prepareSendRequest(msg, timeout);
+ final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+
+ try {
+ final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null);
+ RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+
+ this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ requestResponseFuture.setSendReqeustOk(true);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ requestResponseFuture.setSendReqeustOk(false);
+ requestResponseFuture.putResponseMessage(null);
+ requestResponseFuture.setCause(e);
+ }
+ }, null, timeout);
+
+ Message responseMessage = requestResponseFuture.waitResponseMessage(timeout);
+ if (responseMessage == null) {
+ if (requestResponseFuture.isSendReqeustOk()) {
+ throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
+ "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
+ } else {
+ throw new MQClientException("send request message to <" + msg.getTopic() + "> fail", requestResponseFuture.getCause());
+ }
+ }
+ return responseMessage;
+ } finally {
+ RequestFutureTable.getRequestFutureTable().remove(requestUniqId);
+ }
+ }
+
+ public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
+ throws RemotingException {
+ prepareSendRequest(msg, timeout);
+ final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+
+ try {
+ final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback);
+ RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+
+ this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ requestResponseFuture.setSendReqeustOk(true);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ requestResponseFuture.setCause(e);
+ requestFail(requestUniqId);
+ }
+ }, null, timeout);
+ } catch (Exception ex) {
+ log.warn("send request message to <{}> failed.", msg.getTopic(), ex);
+ throw new RemotingSendRequestException(msg.getTopic(), ex);
+ }
+ }
+
+ private void requestFail(final String requestUniqId) {
+ RequestResponseFuture responseFuture = RequestFutureTable.getRequestFutureTable().remove(requestUniqId);
+ if (responseFuture != null) {
+ responseFuture.setSendReqeustOk(false);
+ responseFuture.putResponseMessage(null);
+ try {
+ responseFuture.executeRequestCallback();
+ } catch (Exception e) {
+ log.warn("execute requestCallback in requestFail, and callback throw", e);
+ }
+ }
+ }
+
+ private void prepareSendRequest(final Message msg, long timeout){
+ String requestUniqId = RequestIdUtil.createUniqueRequestId();
+ String requestClientId = this.getmQClientFactory().getClientId();
+ MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REQUEST_UNIQ_ID, requestUniqId);
+ MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_REPLY_TO, requestClientId);
+ MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_TTL, String.valueOf(timeout));
+
+ boolean hasRouteData = this.getmQClientFactory().getTopicRouteTable().containsKey(msg.getTopic());
+ if (!hasRouteData) {
+ long beginTimestamp = System.currentTimeMillis();
+ this.tryToFindTopicPublishInfo(msg.getTopic());
+ this.getmQClientFactory().sendHeartbeatToAllBrokerWithLock();
+ long cost = System.currentTimeMillis() - beginTimestamp;
+ if (cost > 500) {
+ log.warn("prepare send request for <{}> cost {} ms", msg.getTopic(), cost);
+ }
+ }
+ }
+
+ private SendResult reply(final Message msg, long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null, timeoutMillis);
+ }
+
+ private SendResult reply(final Message msg, final SendCallback sendCallback, long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ return this.sendDefaultImpl(msg, CommunicationMode.ASYNC, sendCallback, timeoutMillis);
+ }
+
+ public void replyOneway(final Message msg) throws RemotingException, MQClientException, InterruptedException {
+ this.sendOneway(msg);
+ }
+
public ConcurrentMap getTopicPublishInfoTable() {
return topicPublishInfoTable;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
index b4acf8f1c3..4789c4d33e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
@@ -24,6 +24,7 @@ import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.Validators;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.exception.RequestTimeoutException;
import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
import org.apache.rocketmq.client.log.ClientLogger;
import org.apache.rocketmq.client.trace.AsyncTraceDispatcher;
@@ -582,6 +583,111 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
this.defaultMQProducerImpl.send(msg, selector, arg, sendCallback, timeout);
}
+ /**
+ *
+ * @param msg
+ * @param timeout
+ * @return
+ * @throws MQClientException
+ * @throws RemotingException
+ * @throws MQBrokerException
+ * @throws InterruptedException
+ */
+ @Override
+ public Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException,
+ RemotingException, MQBrokerException, InterruptedException {
+ msg.setTopic(withNamespace(msg.getTopic()));
+ return this.defaultMQProducerImpl.request(msg, timeout);
+ }
+
+ /**
+ *
+ * @param msg
+ * @param requestCallback
+ * @param timeout
+ * @return
+ * @throws MQClientException
+ * @throws RemotingException
+ * @throws InterruptedException
+ */
+ @Override
+ public void request(final Message msg, final RequestCallback requestCallback, final long timeout)
+ throws MQClientException, RemotingException, InterruptedException, MQBrokerException, RequestTimeoutException {
+ this.defaultMQProducerImpl.request(msg, requestCallback, timeout);
+ }
+
+ /**
+ *
+ * @param msg
+ * @param selector
+ * @param arg
+ * @param timeout
+ * @return
+ * @throws MQClientException
+ * @throws RemotingException
+ * @throws MQBrokerException
+ * @throws InterruptedException
+ */
+ @Override
+ public Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final long timeout) throws MQClientException, RemotingException, MQBrokerException,
+ InterruptedException, RequestTimeoutException {
+ return this.defaultMQProducerImpl.request(msg, selector, arg, timeout);
+ }
+
+ /**
+ *
+ * @param msg
+ * @param selector
+ * @param arg
+ * @param requestCallback
+ * @param timeout
+ * @return
+ * @throws MQClientException
+ * @throws RemotingException
+ * @throws InterruptedException
+ */
+ @Override
+ public void request(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final RequestCallback requestCallback, final long timeout) throws MQClientException, RemotingException,
+ InterruptedException {
+ this.defaultMQProducerImpl.request(msg, selector, arg, requestCallback, timeout);
+ }
+
+ /**
+ *
+ * @param msg
+ * @param mq
+ * @param timeout
+ * @return
+ * @throws MQClientException
+ * @throws RemotingException
+ * @throws MQBrokerException
+ * @throws InterruptedException
+ */
+ @Override
+ public Message request(final Message msg, final MessageQueue mq, final long timeout)
+ throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
+ return this.defaultMQProducerImpl.request(msg, mq, timeout);
+ }
+
+ /**
+ *
+ * @param msg
+ * @param mq
+ * @param requestCallback
+ * @param timeout
+ * @return
+ * @throws MQClientException
+ * @throws RemotingException
+ * @throws InterruptedException
+ */
+ @Override
+ public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
+ throws MQClientException, RemotingException, InterruptedException {
+ this.defaultMQProducerImpl.request(msg, mq, requestCallback, timeout);
+ }
+
/**
* Same to {@link #sendOneway(Message)} with message queue selector specified.
*
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
index 1af6005748..ce8d4a5024 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
@@ -21,6 +21,7 @@ import java.util.List;
import org.apache.rocketmq.client.MQAdmin;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.exception.RequestTimeoutException;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.remoting.exception.RemotingException;
@@ -98,4 +99,25 @@ public interface MQProducer extends MQAdmin {
SendResult send(final Collection msgs, final MessageQueue mq, final long timeout)
throws MQClientException, RemotingException, MQBrokerException, InterruptedException;
+
+ //for rpc
+ Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException,
+ RemotingException, MQBrokerException, InterruptedException;
+
+ void request(final Message msg, final RequestCallback requestCallback, final long timeout)
+ throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException, MQBrokerException;
+
+ Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException,
+ InterruptedException;
+
+ void request(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final RequestCallback requestCallback, final long timeout) throws RequestTimeoutException, MQClientException, RemotingException,
+ InterruptedException;
+
+ Message request(final Message msg, final MessageQueue mq, final long timeout)
+ throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException;
+
+ void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
+ throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java
new file mode 100644
index 0000000000..4a1874f929
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java
@@ -0,0 +1,9 @@
+package org.apache.rocketmq.client.producer;
+
+import org.apache.rocketmq.common.message.Message;
+
+public interface RequestCallback {
+ void onSuccess(final Message message);
+
+ void onException(final Throwable e);
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java
new file mode 100644
index 0000000000..74195be33b
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java
@@ -0,0 +1,46 @@
+package org.apache.rocketmq.client.producer;
+
+import org.apache.rocketmq.client.common.ClientErrorCode;
+import org.apache.rocketmq.client.exception.RequestTimeoutException;
+import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.logging.InternalLogger;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class RequestFutureTable {
+ private static InternalLogger log = ClientLogger.getLog();
+ private static ConcurrentHashMap requestFutureTable = new ConcurrentHashMap();
+
+ public static ConcurrentHashMap getRequestFutureTable(){
+ return requestFutureTable;
+ }
+
+ public static void scanExpiredRequest(){
+ final List rfList = new LinkedList();
+ Iterator> it = requestFutureTable.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry next = it.next();
+ RequestResponseFuture rep = next.getValue();
+
+ if (rep.isTimeout()) {
+ it.remove();
+ rfList.add(rep);
+ log.warn("remove timeout request, REQUEST_UNIQ_ID={}" + rep.getRequestUniqId());
+ }
+ }
+
+ for (RequestResponseFuture rf : rfList) {
+ try {
+ Throwable cause = new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION, "request timeout, no reply message.");
+ rf.setCause(cause);
+ rf.executeRequestCallback();
+ } catch (Throwable e) {
+ log.warn("scanResponseTable, operationComplete Exception", e);
+ }
+ }
+ }
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
new file mode 100644
index 0000000000..a5c5feebdb
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
@@ -0,0 +1,117 @@
+package org.apache.rocketmq.client.producer;
+
+import org.apache.rocketmq.common.message.Message;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class RequestResponseFuture {
+ private final String requestUniqId;
+ private long timeoutMillis;
+ private final RequestCallback requestCallback;
+ private final long beginTimestamp = System.currentTimeMillis();
+ private CountDownLatch countDownLatch = new CountDownLatch(1);
+
+ private AtomicBoolean ececuteCallbackOnlyOnce = new AtomicBoolean(false);
+ private volatile Message responseMsg = null;
+ private volatile boolean sendReqeustOk = true;
+ private volatile Throwable cause = null;
+ private final Message requestMsg = null;
+
+
+ public RequestResponseFuture(String requestUniqId, long timeoutMillis, RequestCallback requestCallback){
+ this.requestUniqId = requestUniqId;
+ this.timeoutMillis = timeoutMillis;
+ this.requestCallback = requestCallback;
+ }
+
+ public void executeRequestCallback(){
+ if (requestCallback != null) {
+ if (sendReqeustOk && cause == null) {
+ requestCallback.onSuccess(responseMsg);
+ } else {
+ requestCallback.onException(cause);
+ }
+ }
+ }
+
+ public boolean isTimeout(){
+ long diff = System.currentTimeMillis() - this.beginTimestamp;
+ return diff > this.timeoutMillis;
+ }
+
+ public Message waitResponseMessage(final long timeout) throws InterruptedException {
+ this.countDownLatch.await(timeout, TimeUnit.MILLISECONDS);
+ return this.responseMsg;
+ }
+
+ public void putResponseMessage(final Message responseMsg){
+ this.responseMsg = responseMsg;
+ this.countDownLatch.countDown();
+ }
+
+ public String getRequestUniqId() {
+ return requestUniqId;
+ }
+
+ public long getTimeoutMillis() {
+ return timeoutMillis;
+ }
+
+ public void setTimeoutMillis(long timeoutMillis) {
+ this.timeoutMillis = timeoutMillis;
+ }
+
+ public RequestCallback getRequestCallback() {
+ return requestCallback;
+ }
+
+ public long getBeginTimestamp() {
+ return beginTimestamp;
+ }
+
+ public CountDownLatch getCountDownLatch() {
+ return countDownLatch;
+ }
+
+ public void setCountDownLatch(CountDownLatch countDownLatch) {
+ this.countDownLatch = countDownLatch;
+ }
+
+ public AtomicBoolean getEcecuteCallbackOnlyOnce() {
+ return ececuteCallbackOnlyOnce;
+ }
+
+ public void setEcecuteCallbackOnlyOnce(AtomicBoolean ececuteCallbackOnlyOnce) {
+ this.ececuteCallbackOnlyOnce = ececuteCallbackOnlyOnce;
+ }
+
+ public Message getResponseMsg() {
+ return responseMsg;
+ }
+
+ public void setResponseMsg(Message responseMsg) {
+ this.responseMsg = responseMsg;
+ }
+
+ public boolean isSendReqeustOk() {
+ return sendReqeustOk;
+ }
+
+ public void setSendReqeustOk(boolean sendReqeustOk) {
+ this.sendReqeustOk = sendReqeustOk;
+ }
+
+ public Message getRequestMsg() {
+ return requestMsg;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+
+ public void setCause(Throwable cause) {
+ this.cause = cause;
+ }
+}
diff --git a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
new file mode 100644
index 0000000000..ce41775227
--- /dev/null
+++ b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
@@ -0,0 +1,30 @@
+package org.apache.rocketmq.client.utils;
+
+import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageAccessor;
+import org.apache.rocketmq.common.message.MessageConst;
+
+public class MessageUtil {
+ public static Message createReplyMessage(final Message requestMessage) {
+ if (requestMessage != null) {
+ Message replyMessage = new Message();
+ String cluster = requestMessage.getProperty(MessageConst.PROPERTY_CLUSTER);
+ String replyTo = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
+ String requestUniqId = requestMessage.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
+ String ttl = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_TTL);
+ if (cluster == null) {
+
+ }
+ String replyTopic = MixAll.getReplyTopic(cluster);
+ replyMessage.setTopic(replyTopic);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TYPE, MixAll.REPLY_MESSAGE_FLAG);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_REQUEST_UNIQ_ID, requestUniqId);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_REPLY_TO, replyTo);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TTL, ttl);
+
+ return replyMessage;
+ }
+ return null;
+ }
+}
diff --git a/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java b/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java
index 1c3f37d00d..c3613e7d4c 100644
--- a/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java
+++ b/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java
@@ -61,6 +61,7 @@ public class BrokerConfig {
*/
private int sendMessageThreadPoolNums = 1; //16 + Runtime.getRuntime().availableProcessors() * 4;
private int pullMessageThreadPoolNums = 16 + Runtime.getRuntime().availableProcessors() * 2;
+ private int processReplyMessageThreadPoolNums = 16 + Runtime.getRuntime().availableProcessors() * 2;
private int queryMessageThreadPoolNums = 8 + Runtime.getRuntime().availableProcessors();
private int adminBrokerThreadPoolNums = 16;
@@ -83,6 +84,7 @@ public class BrokerConfig {
private boolean fetchNamesrvAddrByAddressServer = false;
private int sendThreadPoolQueueCapacity = 10000;
private int pullThreadPoolQueueCapacity = 100000;
+ private int replyThreadPoolQueueCapacity = 10000;
private int queryThreadPoolQueueCapacity = 20000;
private int clientManagerThreadPoolQueueCapacity = 1000000;
private int consumerManagerThreadPoolQueueCapacity = 1000000;
@@ -180,6 +182,8 @@ public class BrokerConfig {
@ImportantField
private boolean aclEnable = false;
+ private boolean storeReplyMessageEnable = true;
+
public static String localHostName() {
try {
return InetAddress.getLocalHost().getHostName();
@@ -374,6 +378,14 @@ public class BrokerConfig {
this.pullMessageThreadPoolNums = pullMessageThreadPoolNums;
}
+ public int getProcessReplyMessageThreadPoolNums() {
+ return processReplyMessageThreadPoolNums;
+ }
+
+ public void setProcessReplyMessageThreadPoolNums(int processReplyMessageThreadPoolNums) {
+ this.processReplyMessageThreadPoolNums = processReplyMessageThreadPoolNums;
+ }
+
public int getQueryMessageThreadPoolNums() {
return queryMessageThreadPoolNums;
}
@@ -470,6 +482,14 @@ public class BrokerConfig {
this.pullThreadPoolQueueCapacity = pullThreadPoolQueueCapacity;
}
+ public int getReplyThreadPoolQueueCapacity() {
+ return replyThreadPoolQueueCapacity;
+ }
+
+ public void setReplyThreadPoolQueueCapacity(int replyThreadPoolQueueCapacity) {
+ this.replyThreadPoolQueueCapacity = replyThreadPoolQueueCapacity;
+ }
+
public int getQueryThreadPoolQueueCapacity() {
return queryThreadPoolQueueCapacity;
}
@@ -765,4 +785,12 @@ public class BrokerConfig {
public void setAclEnable(boolean aclEnable) {
this.aclEnable = aclEnable;
}
+
+ public boolean isStoreReplyMessageEnable() {
+ return storeReplyMessageEnable;
+ }
+
+ public void setStoreReplyMessageEnable(boolean storeReplyMessageEnable) {
+ this.storeReplyMessageEnable = storeReplyMessageEnable;
+ }
}
diff --git a/common/src/main/java/org/apache/rocketmq/common/MixAll.java b/common/src/main/java/org/apache/rocketmq/common/MixAll.java
index 0af65dff0f..a6151e55f7 100644
--- a/common/src/main/java/org/apache/rocketmq/common/MixAll.java
+++ b/common/src/main/java/org/apache/rocketmq/common/MixAll.java
@@ -84,6 +84,7 @@ public class MixAll {
public static final String RETRY_GROUP_TOPIC_PREFIX = "%RETRY%";
public static final String DLQ_GROUP_TOPIC_PREFIX = "%DLQ%";
+ public static final String REPLY_TOPIC_POSTFIX = "REPLY_TOPIC";
public static final String SYSTEM_TOPIC_PREFIX = "rmq_sys_";
public static final String UNIQUE_MSG_QUERY_FLAG = "_UNIQUE_KEY_QUERY";
public static final String DEFAULT_TRACE_REGION_ID = "DefaultRegion";
@@ -96,6 +97,8 @@ public class MixAll {
public static final String CID_SYS_RMQ_TRANS = "CID_RMQ_SYS_TRANS";
public static final String ACL_CONF_TOOLS_FILE = "/conf/tools.yml";
+ public static final String REPLY_MESSAGE_FLAG = "reply";
+
public static String getWSAddr() {
String wsDomainName = System.getProperty("rocketmq.namesrv.domain", DEFAULT_NAMESRV_ADDR_LOOKUP);
String wsDomainSubgroup = System.getProperty("rocketmq.namesrv.domain.subgroup", "nsaddr");
@@ -110,6 +113,10 @@ public class MixAll {
return RETRY_GROUP_TOPIC_PREFIX + consumerGroup;
}
+ public static String getReplyTopic(final String clusterName) {
+ return clusterName + "_" + REPLY_TOPIC_POSTFIX;
+ }
+
public static boolean isSysConsumerGroup(final String consumerGroup) {
return consumerGroup.startsWith(CID_RMQ_SYS_PREFIX);
}
diff --git a/common/src/main/java/org/apache/rocketmq/common/message/MessageConst.java b/common/src/main/java/org/apache/rocketmq/common/message/MessageConst.java
index aa8481643a..178e417c7a 100644
--- a/common/src/main/java/org/apache/rocketmq/common/message/MessageConst.java
+++ b/common/src/main/java/org/apache/rocketmq/common/message/MessageConst.java
@@ -45,6 +45,13 @@ public class MessageConst {
public static final String PROPERTY_TRANSACTION_CHECK_TIMES = "TRANSACTION_CHECK_TIMES";
public static final String PROPERTY_CHECK_IMMUNITY_TIME_IN_SECONDS = "CHECK_IMMUNITY_TIME_IN_SECONDS";
public static final String PROPERTY_INSTANCE_ID = "INSTANCE_ID";
+ public static final String PROPERTY_REQUEST_UNIQ_ID = "REQUEST_UNIQ_ID";
+ public static final String PROPERTY_MESSAGE_REPLY_TO = "REPLY_TO";
+ public static final String PROPERTY_MESSAGE_TTL = "TTL";
+ public static final String PROPERTY_REPLY_MESSAGE_ARRIVE_TIME = "ARRIVE_TIME";
+ public static final String PROPERTY_PUSH_REPLY_TIME = "PUSH_REPLY_TIME";
+ public static final String PROPERTY_CLUSTER = "CLUSTER";
+ public static final String PROPERTY_MESSAGE_TYPE = "MSG_TYPE";
public static final String KEY_SEPARATOR = " ";
@@ -74,5 +81,12 @@ public class MessageConst {
STRING_HASH_SET.add(PROPERTY_MAX_RECONSUME_TIMES);
STRING_HASH_SET.add(PROPERTY_CONSUME_START_TIMESTAMP);
STRING_HASH_SET.add(PROPERTY_INSTANCE_ID);
+ STRING_HASH_SET.add(PROPERTY_REQUEST_UNIQ_ID);
+ STRING_HASH_SET.add(PROPERTY_MESSAGE_REPLY_TO);
+ STRING_HASH_SET.add(PROPERTY_MESSAGE_TTL);
+ STRING_HASH_SET.add(PROPERTY_REPLY_MESSAGE_ARRIVE_TIME);
+ STRING_HASH_SET.add(PROPERTY_PUSH_REPLY_TIME);
+ STRING_HASH_SET.add(PROPERTY_CLUSTER);
+ STRING_HASH_SET.add(PROPERTY_MESSAGE_TYPE);
}
}
diff --git a/common/src/main/java/org/apache/rocketmq/common/protocol/RequestCode.java b/common/src/main/java/org/apache/rocketmq/common/protocol/RequestCode.java
index 58c4b9fe90..ef7f2a1f4d 100644
--- a/common/src/main/java/org/apache/rocketmq/common/protocol/RequestCode.java
+++ b/common/src/main/java/org/apache/rocketmq/common/protocol/RequestCode.java
@@ -180,4 +180,10 @@ public class RequestCode {
* resume logic of checking half messages that have been put in TRANS_CHECK_MAXTIME_TOPIC before
*/
public static final int RESUME_CHECK_HALF_MESSAGE = 323;
+
+ public static final int SEND_REPLY_MESSAGE = 324;
+
+ public static final int SEND_REPLY_MESSAGE_V2 = 325;
+
+ public static final int PUSH_REPLY_MESSAGE_TO_CLIENT = 326;
}
diff --git a/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java b/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java
new file mode 100644
index 0000000000..465baeae86
--- /dev/null
+++ b/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java
@@ -0,0 +1,153 @@
+package org.apache.rocketmq.common.protocol.header;
+
+import org.apache.rocketmq.remoting.CommandCustomHeader;
+import org.apache.rocketmq.remoting.annotation.CFNotNull;
+import org.apache.rocketmq.remoting.annotation.CFNullable;
+import org.apache.rocketmq.remoting.exception.RemotingCommandException;
+
+public class ReplyMessageRequestHeader implements CommandCustomHeader {
+ @CFNotNull
+ private String producerGroup;
+ @CFNotNull
+ private String topic;
+ @CFNotNull
+ private String defaultTopic;
+ @CFNotNull
+ private Integer defaultTopicQueueNums;
+ @CFNotNull
+ private Integer queueId;
+ @CFNotNull
+ private Integer sysFlag;
+ @CFNotNull
+ private Long bornTimestamp;
+ @CFNotNull
+ private Integer flag;
+ @CFNullable
+ private String properties;
+ @CFNullable
+ private Integer reconsumeTimes;
+ @CFNullable
+ private boolean unitMode = false;
+
+ @CFNotNull
+ private String bornHost;
+ @CFNotNull
+ private String storeHost;
+ @CFNotNull
+ private long storeTimestamp;
+
+ public void checkFields() throws RemotingCommandException {
+ }
+
+ public String getProducerGroup() {
+ return producerGroup;
+ }
+
+ public void setProducerGroup(String producerGroup) {
+ this.producerGroup = producerGroup;
+ }
+
+ public String getTopic() {
+ return topic;
+ }
+
+ public void setTopic(String topic) {
+ this.topic = topic;
+ }
+
+ public String getDefaultTopic() {
+ return defaultTopic;
+ }
+
+ public void setDefaultTopic(String defaultTopic) {
+ this.defaultTopic = defaultTopic;
+ }
+
+ public Integer getDefaultTopicQueueNums() {
+ return defaultTopicQueueNums;
+ }
+
+ public void setDefaultTopicQueueNums(Integer defaultTopicQueueNums) {
+ this.defaultTopicQueueNums = defaultTopicQueueNums;
+ }
+
+ public Integer getQueueId() {
+ return queueId;
+ }
+
+ public void setQueueId(Integer queueId) {
+ this.queueId = queueId;
+ }
+
+ public Integer getSysFlag() {
+ return sysFlag;
+ }
+
+ public void setSysFlag(Integer sysFlag) {
+ this.sysFlag = sysFlag;
+ }
+
+ public Long getBornTimestamp() {
+ return bornTimestamp;
+ }
+
+ public void setBornTimestamp(Long bornTimestamp) {
+ this.bornTimestamp = bornTimestamp;
+ }
+
+ public Integer getFlag() {
+ return flag;
+ }
+
+ public void setFlag(Integer flag) {
+ this.flag = flag;
+ }
+
+ public String getProperties() {
+ return properties;
+ }
+
+ public void setProperties(String properties) {
+ this.properties = properties;
+ }
+
+ public Integer getReconsumeTimes() {
+ return reconsumeTimes;
+ }
+
+ public void setReconsumeTimes(Integer reconsumeTimes) {
+ this.reconsumeTimes = reconsumeTimes;
+ }
+
+ public boolean isUnitMode() {
+ return unitMode;
+ }
+
+ public void setUnitMode(boolean unitMode) {
+ this.unitMode = unitMode;
+ }
+
+ public String getBornHost() {
+ return bornHost;
+ }
+
+ public void setBornHost(String bornHost) {
+ this.bornHost = bornHost;
+ }
+
+ public String getStoreHost() {
+ return storeHost;
+ }
+
+ public void setStoreHost(String storeHost) {
+ this.storeHost = storeHost;
+ }
+
+ public long getStoreTimestamp() {
+ return storeTimestamp;
+ }
+
+ public void setStoreTimestamp(long storeTimestamp) {
+ this.storeTimestamp = storeTimestamp;
+ }
+}
diff --git a/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java b/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java
new file mode 100644
index 0000000000..9a58e5fdb6
--- /dev/null
+++ b/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java
@@ -0,0 +1,9 @@
+package org.apache.rocketmq.common.utils;
+
+import java.util.UUID;
+
+public class RequestIdUtil {
+ public static String createUniqueRequestId(){
+ return UUID.randomUUID().toString();
+ }
+}
From 46b2e1250b7d728b3a2212624603e785c578bdf1 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Tue, 27 Aug 2019 21:16:31 +0800
Subject: [PATCH 02/26] [RIP-16]impl rpc support - code format
---
.../rocketmq/broker/BrokerController.java | 37 ++++------
.../broker/client/ProducerManager.java | 3 +-
.../processor/ReplyMessageProcessor.java | 70 ++++++++++++------
.../broker/topic/TopicConfigManager.java | 4 +-
.../exception/RequestTimeoutException.java | 20 +++++-
.../client/impl/ClientRemotingProcessor.java | 14 ++--
.../rocketmq/client/impl/MQClientAPIImpl.java | 12 ++--
.../impl/producer/DefaultMQProducerImpl.java | 69 +++++++++---------
.../client/producer/DefaultMQProducer.java | 72 +++++++------------
.../rocketmq/client/producer/MQProducer.java | 17 ++---
.../client/producer/RequestCallback.java | 17 +++++
.../client/producer/RequestFutureTable.java | 30 ++++++--
.../producer/RequestResponseFuture.java | 34 ++++++---
.../rocketmq/client/utils/MessageUtil.java | 17 +++++
.../apache/rocketmq/common/BrokerConfig.java | 2 +-
.../org/apache/rocketmq/common/MixAll.java | 8 +--
.../header/ReplyMessageRequestHeader.java | 17 +++++
.../rocketmq/common/utils/RequestIdUtil.java | 19 ++++-
18 files changed, 284 insertions(+), 178 deletions(-)
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java b/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
index 84b3e024ae..8739d9fc62 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/BrokerController.java
@@ -61,8 +61,8 @@ import org.apache.rocketmq.broker.processor.ConsumerManageProcessor;
import org.apache.rocketmq.broker.processor.EndTransactionProcessor;
import org.apache.rocketmq.broker.processor.PullMessageProcessor;
import org.apache.rocketmq.broker.processor.QueryMessageProcessor;
-import org.apache.rocketmq.broker.processor.SendMessageProcessor;
import org.apache.rocketmq.broker.processor.ReplyMessageProcessor;
+import org.apache.rocketmq.broker.processor.SendMessageProcessor;
import org.apache.rocketmq.broker.slave.SlaveSynchronize;
import org.apache.rocketmq.broker.subscription.SubscriptionGroupManager;
import org.apache.rocketmq.broker.topic.TopicConfigManager;
@@ -166,7 +166,7 @@ public class BrokerController {
private TransactionalMessageService transactionalMessageService;
private AbstractTransactionalMessageCheckListener transactionalMessageCheckListener;
private Future> slaveSyncFuture;
- private Map accessValidatorMap = new HashMap();
+ private Map accessValidatorMap = new HashMap();
public BrokerController(
final BrokerConfig brokerConfig,
@@ -245,7 +245,7 @@ public class BrokerController {
this.brokerConfig);
if (messageStoreConfig.isEnableDLegerCommitLog()) {
DLedgerRoleChangeHandler roleChangeHandler = new DLedgerRoleChangeHandler(this, (DefaultMessageStore) messageStore);
- ((DLedgerCommitLog)((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
+ ((DLedgerCommitLog) ((DefaultMessageStore) messageStore).getCommitLog()).getdLedgerServer().getdLedgerLeaderElector().addRoleChangeHandler(roleChangeHandler);
}
this.brokerStats = new BrokerStats((DefaultMessageStore) this.messageStore);
//load plugin
@@ -282,12 +282,12 @@ public class BrokerController {
new ThreadFactoryImpl("PullMessageThread_"));
this.replyMessageExecutor = new BrokerFixedThreadPoolExecutor(
- this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
- this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
- 1000 * 60,
- TimeUnit.MILLISECONDS,
- this.replyThreadPoolQueue,
- new ThreadFactoryImpl("ProcessReplyMessageThread_"));
+ this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
+ this.brokerConfig.getProcessReplyMessageThreadPoolNums(),
+ 1000 * 60,
+ TimeUnit.MILLISECONDS,
+ this.replyThreadPoolQueue,
+ new ThreadFactoryImpl("ProcessReplyMessageThread_"));
this.queryMessageExecutor = new BrokerFixedThreadPoolExecutor(
this.brokerConfig.getQueryMessageThreadPoolNums(),
@@ -513,9 +513,9 @@ public class BrokerController {
return;
}
- for (AccessValidator accessValidator: accessValidators) {
+ for (AccessValidator accessValidator : accessValidators) {
final AccessValidator validator = accessValidator;
- accessValidatorMap.put(validator.getClass(),validator);
+ accessValidatorMap.put(validator.getClass(), validator);
this.registerServerRPCHook(new RPCHook() {
@Override
@@ -531,14 +531,13 @@ public class BrokerController {
}
}
-
private void initialRpcHooks() {
List rpcHooks = ServiceProvider.load(ServiceProvider.RPC_HOOK_ID, RPCHook.class);
if (rpcHooks == null || rpcHooks.isEmpty()) {
return;
}
- for (RPCHook rpcHook: rpcHooks) {
+ for (RPCHook rpcHook : rpcHooks) {
this.registerServerRPCHook(rpcHook);
}
}
@@ -576,7 +575,6 @@ public class BrokerController {
this.fastRemotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE, replyMessageProcessor, replyMessageExecutor);
this.fastRemotingServer.registerProcessor(RequestCode.SEND_REPLY_MESSAGE_V2, replyMessageProcessor, replyMessageExecutor);
-
/**
* QueryMessageProcessor
*/
@@ -887,8 +885,6 @@ public class BrokerController {
handleSlaveSynchronize(messageStoreConfig.getBrokerRole());
}
-
-
this.registerBrokerAll(true, false, true);
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@@ -911,7 +907,6 @@ public class BrokerController {
this.brokerFastFailure.start();
}
-
}
public synchronized void registerIncrementBrokerData(TopicConfig topicConfig, DataVersion dataVersion) {
@@ -1125,7 +1120,6 @@ public class BrokerController {
this.transactionalMessageCheckListener = transactionalMessageCheckListener;
}
-
public BlockingQueue getEndTransactionThreadPoolQueue() {
return endTransactionThreadPoolQueue;
@@ -1146,8 +1140,7 @@ public class BrokerController {
public void run() {
try {
BrokerController.this.slaveSynchronize.syncAll();
- }
- catch (Throwable e) {
+ } catch (Throwable e) {
log.error("ScheduledTask SlaveSynchronize syncAll error.", e);
}
}
@@ -1193,8 +1186,6 @@ public class BrokerController {
log.info("Finish to change to slave brokerName={} brokerId={}", brokerConfig.getBrokerName(), brokerId);
}
-
-
public void changeToMaster(BrokerRole role) {
if (role == BrokerRole.SLAVE) {
return;
@@ -1244,6 +1235,4 @@ public class BrokerController {
}
}
-
-
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
index db372fa8c8..bd007b0531 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/client/ProducerManager.java
@@ -17,7 +17,6 @@
package org.apache.rocketmq.broker.client;
import io.netty.channel.Channel;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
@@ -28,7 +27,6 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
-
import org.apache.rocketmq.broker.util.PositiveAtomicCounter;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.logging.InternalLogger;
@@ -46,6 +44,7 @@ public class ProducerManager {
new HashMap>();
private final ConcurrentHashMap clientChannelTable = new ConcurrentHashMap<>();
private PositiveAtomicCounter positiveAtomicCounter = new PositiveAtomicCounter();
+
public ProducerManager() {
}
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
index 00960d7990..23e1e9ac8b 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
@@ -1,11 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.rocketmq.broker.processor;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.mqtrace.SendMessageContext;
-import org.apache.rocketmq.common.*;
-import org.apache.rocketmq.common.message.*;
+import org.apache.rocketmq.common.TopicConfig;
+import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageAccessor;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
import org.apache.rocketmq.common.protocol.header.ReplyMessageRequestHeader;
@@ -16,7 +38,8 @@ import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-import org.apache.rocketmq.store.*;
+import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class ReplyMessageProcessor extends AbstractSendMessageProcessor implements NettyRequestProcessor {
@@ -26,7 +49,8 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
}
@Override
- public RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException {
+ public RemotingCommand processRequest(ChannelHandlerContext ctx,
+ RemotingCommand request) throws RemotingCommandException {
SendMessageContext mqtraceContext = null;
SendMessageRequestHeader requestHeader = parseRequestHeader(request);
if (requestHeader == null) {
@@ -49,13 +73,13 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
switch (request.getCode()) {
case RequestCode.SEND_REPLY_MESSAGE_V2:
requestHeaderV2 =
- (SendMessageRequestHeaderV2) request
- .decodeCommandCustomHeader(SendMessageRequestHeaderV2.class);
+ (SendMessageRequestHeaderV2) request
+ .decodeCommandCustomHeader(SendMessageRequestHeaderV2.class);
case RequestCode.SEND_REPLY_MESSAGE:
if (null == requestHeaderV2) {
requestHeader =
- (SendMessageRequestHeader) request
- .decodeCommandCustomHeader(SendMessageRequestHeader.class);
+ (SendMessageRequestHeader) request
+ .decodeCommandCustomHeader(SendMessageRequestHeader.class);
} else {
requestHeader = SendMessageRequestHeaderV2.createSendMessageRequestHeaderV1(requestHeaderV2);
}
@@ -66,11 +90,11 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
}
private RemotingCommand processReplyMessageRequest(final ChannelHandlerContext ctx,
- final RemotingCommand request,
- final SendMessageContext sendMessageContext,
- final SendMessageRequestHeader requestHeader) {
+ final RemotingCommand request,
+ final SendMessageContext sendMessageContext,
+ final SendMessageRequestHeader requestHeader) {
final RemotingCommand response = RemotingCommand.createResponseCommand(SendMessageResponseHeader.class);
- final SendMessageResponseHeader responseHeader = (SendMessageResponseHeader)response.readCustomHeader();
+ final SendMessageResponseHeader responseHeader = (SendMessageResponseHeader) response.readCustomHeader();
response.setOpaque(request.getOpaque());
@@ -126,7 +150,8 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
return response;
}
- private boolean pushReplyMessage(final ChannelHandlerContext ctx, final SendMessageRequestHeader requestHeader, final Message msg, final RemotingCommand response) {
+ private boolean pushReplyMessage(final ChannelHandlerContext ctx, final SendMessageRequestHeader requestHeader,
+ final Message msg, final RemotingCommand response) {
ReplyMessageRequestHeader replyMessageRequestHeader = new ReplyMessageRequestHeader();
replyMessageRequestHeader.setBornHost(ctx.channel().remoteAddress().toString());
replyMessageRequestHeader.setStoreHost(this.getStoreHost().toString());
@@ -194,12 +219,13 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
}
private void handlePutMessageResult(PutMessageResult putMessageResult, final RemotingCommand response,
- final RemotingCommand request, final MessageExt msg,
- final SendMessageResponseHeader responseHeader, SendMessageContext sendMessageContext, ChannelHandlerContext ctx,
- int queueIdInt) {
+ final RemotingCommand request, final MessageExt msg,
+ final SendMessageResponseHeader responseHeader, SendMessageContext sendMessageContext,
+ ChannelHandlerContext ctx,
+ int queueIdInt) {
if (putMessageResult == null) {
response.setRemark("push reply to requester success, but store putMessage return null");
- return ;
+ return;
}
boolean sendOK = false;
@@ -231,12 +257,12 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
case PROPERTIES_SIZE_EXCEEDED:
// response.setCode(ResponseCode.MESSAGE_ILLEGAL);
response.setRemark(
- "the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k, msg properties length limit 32k.");
+ "the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k, msg properties length limit 32k.");
break;
case SERVICE_NOT_AVAILABLE:
// response.setCode(ResponseCode.SERVICE_NOT_AVAILABLE);
response.setRemark(
- "service not available now, maybe disk full, maybe your broker machine memory too small.");
+ "service not available now, maybe disk full, maybe your broker machine memory too small.");
break;
case OS_PAGECACHE_BUSY:
// response.setCode(ResponseCode.SYSTEM_ERROR);
@@ -256,7 +282,7 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
if (sendOK) {
this.brokerController.getBrokerStatsManager().incTopicPutNums(msg.getTopic(), putMessageResult.getAppendMessageResult().getMsgNum(), 1);
this.brokerController.getBrokerStatsManager().incTopicPutSize(msg.getTopic(),
- putMessageResult.getAppendMessageResult().getWroteBytes());
+ putMessageResult.getAppendMessageResult().getWroteBytes());
this.brokerController.getBrokerStatsManager().incBrokerPutNums(putMessageResult.getAppendMessageResult().getMsgNum());
response.setRemark(null);
responseHeader.setMsgId(putMessageResult.getAppendMessageResult().getMsgId());
@@ -270,7 +296,7 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
int commercialBaseCount = brokerController.getBrokerConfig().getCommercialBaseCount();
int wroteSize = putMessageResult.getAppendMessageResult().getWroteBytes();
- int incValue = (int)Math.ceil(wroteSize / BrokerStatsManager.SIZE_PER_COUNT) * commercialBaseCount;
+ int incValue = (int) Math.ceil(wroteSize / BrokerStatsManager.SIZE_PER_COUNT) * commercialBaseCount;
sendMessageContext.setCommercialSendStats(BrokerStatsManager.StatsType.SEND_SUCCESS);
sendMessageContext.setCommercialSendTimes(incValue);
@@ -280,7 +306,7 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
} else {
if (hasSendMessageHook()) {
int wroteSize = request.getBody().length;
- int incValue = (int)Math.ceil(wroteSize / BrokerStatsManager.SIZE_PER_COUNT);
+ int incValue = (int) Math.ceil(wroteSize / BrokerStatsManager.SIZE_PER_COUNT);
sendMessageContext.setCommercialSendStats(BrokerStatsManager.StatsType.SEND_FAILURE);
sendMessageContext.setCommercialSendTimes(incValue);
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
index 577fff57ee..cb2901117f 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/topic/TopicConfigManager.java
@@ -34,11 +34,11 @@ import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.common.constant.PermName;
-import org.apache.rocketmq.logging.InternalLogger;
-import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.common.protocol.body.KVTable;
import org.apache.rocketmq.common.protocol.body.TopicConfigSerializeWrapper;
import org.apache.rocketmq.common.sysflag.TopicSysFlag;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
public class TopicConfigManager extends ConfigManager {
private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
diff --git a/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java b/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java
index fd338d6004..2d756ece61 100644
--- a/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java
+++ b/client/src/main/java/org/apache/rocketmq/client/exception/RequestTimeoutException.java
@@ -1,7 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.rocketmq.client.exception;
import org.apache.rocketmq.common.UtilAll;
-import org.apache.rocketmq.common.help.FAQUrl;
public class RequestTimeoutException extends Exception {
private static final long serialVersionUID = -5758410930844185841L;
@@ -16,7 +32,7 @@ public class RequestTimeoutException extends Exception {
public RequestTimeoutException(int responseCode, String errorMessage) {
super("CODE: " + UtilAll.responseCode2String(responseCode) + " DESC: "
- + errorMessage);
+ + errorMessage);
this.responseCode = responseCode;
this.errorMessage = errorMessage;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
index 7a17a04307..e9072df3a6 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
@@ -16,13 +16,12 @@
*/
package org.apache.rocketmq.client.impl;
+import io.netty.channel.ChannelHandlerContext;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Map;
-
-import io.netty.channel.ChannelHandlerContext;
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.client.impl.producer.MQProducerInner;
@@ -30,7 +29,11 @@ import org.apache.rocketmq.client.log.ClientLogger;
import org.apache.rocketmq.client.producer.RequestFutureTable;
import org.apache.rocketmq.client.producer.RequestResponseFuture;
import org.apache.rocketmq.common.UtilAll;
-import org.apache.rocketmq.common.message.*;
+import org.apache.rocketmq.common.message.MessageAccessor;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.NamespaceUtil;
import org.apache.rocketmq.common.protocol.RequestCode;
import org.apache.rocketmq.common.protocol.ResponseCode;
@@ -43,8 +46,8 @@ import org.apache.rocketmq.common.protocol.header.ConsumeMessageDirectlyResultRe
import org.apache.rocketmq.common.protocol.header.GetConsumerRunningInfoRequestHeader;
import org.apache.rocketmq.common.protocol.header.GetConsumerStatusRequestHeader;
import org.apache.rocketmq.common.protocol.header.NotifyConsumerIdsChangedRequestHeader;
-import org.apache.rocketmq.common.protocol.header.ResetOffsetRequestHeader;
import org.apache.rocketmq.common.protocol.header.ReplyMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.ResetOffsetRequestHeader;
import org.apache.rocketmq.common.sysflag.MessageSysFlag;
import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.common.RemotingHelper;
@@ -52,7 +55,6 @@ import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
import org.apache.rocketmq.remoting.protocol.RemotingCommand;
-
public class ClientRemotingProcessor implements NettyRequestProcessor {
private final InternalLogger log = ClientLogger.getLog();
private final MQClientInstance mqClientFactory;
@@ -221,7 +223,7 @@ public class ClientRemotingProcessor implements NettyRequestProcessor {
}
private RemotingCommand receiveReplyMssage(ChannelHandlerContext ctx,
- RemotingCommand request) throws RemotingCommandException {
+ RemotingCommand request) throws RemotingCommandException {
final RemotingCommand response = RemotingCommand.createResponseCommand(null);
long receiveTime = System.currentTimeMillis();
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
index f780adf9de..d478d7410d 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/MQClientAPIImpl.java
@@ -27,7 +27,6 @@ import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.consumer.PullCallback;
@@ -304,8 +303,8 @@ public class MQClientAPIImpl {
requestHeader.setDefaultGroupPerm(plainAccessConfig.getDefaultGroupPerm());
requestHeader.setDefaultTopicPerm(plainAccessConfig.getDefaultTopicPerm());
requestHeader.setWhiteRemoteAddress(plainAccessConfig.getWhiteRemoteAddress());
- requestHeader.setTopicPerms(UtilAll.List2String(plainAccessConfig.getTopicPerms(),","));
- requestHeader.setGroupPerms(UtilAll.List2String(plainAccessConfig.getGroupPerms(),","));
+ requestHeader.setTopicPerms(UtilAll.List2String(plainAccessConfig.getTopicPerms(), ","));
+ requestHeader.setGroupPerms(UtilAll.List2String(plainAccessConfig.getGroupPerms(), ","));
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.UPDATE_AND_CREATE_ACL_CONFIG, requestHeader);
@@ -344,7 +343,7 @@ public class MQClientAPIImpl {
throw new MQClientException(response.getCode(), response.getRemark());
}
- public void updateGlobalWhiteAddrsConfig(final String addr, final String globalWhiteAddrs,final long timeoutMillis)
+ public void updateGlobalWhiteAddrsConfig(final String addr, final String globalWhiteAddrs, final long timeoutMillis)
throws RemotingException, MQBrokerException, InterruptedException, MQClientException {
UpdateGlobalWhiteAddrsConfigRequestHeader requestHeader = new UpdateGlobalWhiteAddrsConfigRequestHeader();
@@ -366,7 +365,8 @@ public class MQClientAPIImpl {
throw new MQClientException(response.getCode(), response.getRemark());
}
- public ClusterAclVersionInfo getBrokerClusterAclInfo(final String addr,final long timeoutMillis) throws RemotingCommandException, InterruptedException, RemotingTimeoutException,
+ public ClusterAclVersionInfo getBrokerClusterAclInfo(final String addr,
+ final long timeoutMillis) throws RemotingCommandException, InterruptedException, RemotingTimeoutException,
RemotingSendRequestException, RemotingConnectException, MQBrokerException {
RemotingCommand request = RemotingCommand.createRequestCommand(RequestCode.GET_BROKER_CLUSTER_ACL_INFO, null);
@@ -389,7 +389,7 @@ public class MQClientAPIImpl {
}
throw new MQBrokerException(response.getCode(), response.getRemark());
-
+
}
public SendResult sendMessage(
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
index 7a0bc4cd98..6e15ed1a09 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
@@ -103,19 +103,17 @@ public class DefaultMQProducerImpl implements MQProducerInner {
new ConcurrentHashMap();
private final ArrayList sendMessageHookList = new ArrayList();
private final RPCHook rpcHook;
+ private final BlockingQueue asyncSenderThreadPoolQueue;
+ private final ExecutorService defaultAsyncSenderExecutor;
+ private final Timer timer = new Timer("RequestHouseKeepingService", true);
protected BlockingQueue checkRequestQueue;
protected ExecutorService checkExecutor;
private ServiceState serviceState = ServiceState.CREATE_JUST;
private MQClientInstance mQClientFactory;
private ArrayList checkForbiddenHookList = new ArrayList();
private int zipCompressLevel = Integer.parseInt(System.getProperty(MixAll.MESSAGE_COMPRESS_LEVEL, "5"));
-
private MQFaultStrategy mqFaultStrategy = new MQFaultStrategy();
-
- private final BlockingQueue asyncSenderThreadPoolQueue;
- private final ExecutorService defaultAsyncSenderExecutor;
private ExecutorService asyncSenderExecutor;
- private final Timer timer = new Timer("RequestHouseKeepingService", true);
public DefaultMQProducerImpl(final DefaultMQProducer defaultMQProducer) {
this(defaultMQProducer, null);
@@ -291,6 +289,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
/**
* This method will be removed in the version 5.0.0 and getCheckListener is recommended.
+ *
* @return
*/
@Override
@@ -484,13 +483,14 @@ public class DefaultMQProducerImpl implements MQProducerInner {
* DEFAULT ASYNC -------------------------------------------------------
*/
public void send(Message msg,
- SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException {
+ SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException {
send(msg, sendCallback, this.defaultMQProducer.getSendMsgTimeout());
}
/**
- * It will be removed at 4.4.0 cause for exception handling and the wrong Semantics of timeout.
- * A new one will be provided in next version
+ * It will be removed at 4.4.0 cause for exception handling and the wrong Semantics of timeout. A new one will be
+ * provided in next version
+ *
* @param msg
* @param sendCallback
* @param timeout the sendCallback will be invoked at most time
@@ -525,7 +525,6 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
-
public MessageQueue selectOneMessageQueue(final TopicPublishInfo tpInfo, final String lastBrokerName) {
return this.mqFaultStrategy.selectOneMessageQueue(tpInfo, lastBrokerName);
}
@@ -701,11 +700,11 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
private SendResult sendKernelImpl(final Message msg,
- final MessageQueue mq,
- final CommunicationMode communicationMode,
- final SendCallback sendCallback,
- final TopicPublishInfo topicPublishInfo,
- final long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
+ final MessageQueue mq,
+ final CommunicationMode communicationMode,
+ final SendCallback sendCallback,
+ final TopicPublishInfo topicPublishInfo,
+ final long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
long beginStartTime = System.currentTimeMillis();
String brokerAddr = this.mQClientFactory.findBrokerAddressInPublish(mq.getBrokerName());
if (null == brokerAddr) {
@@ -1010,8 +1009,9 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
/**
- * It will be removed at 4.4.0 cause for exception handling and the wrong Semantics of timeout.
- * A new one will be provided in next version
+ * It will be removed at 4.4.0 cause for exception handling and the wrong Semantics of timeout. A new one will be
+ * provided in next version
+ *
* @param msg
* @param mq
* @param sendCallback
@@ -1137,8 +1137,9 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
/**
- * It will be removed at 4.4.0 cause for exception handling and the wrong Semantics of timeout.
- * A new one will be provided in next version
+ * It will be removed at 4.4.0 cause for exception handling and the wrong Semantics of timeout. A new one will be
+ * provided in next version
+ *
* @param msg
* @param selector
* @param arg
@@ -1149,7 +1150,8 @@ public class DefaultMQProducerImpl implements MQProducerInner {
* @throws InterruptedException
*/
@Deprecated
- public void send(final Message msg, final MessageQueueSelector selector, final Object arg, final SendCallback sendCallback, final long timeout)
+ public void send(final Message msg, final MessageQueueSelector selector, final Object arg,
+ final SendCallback sendCallback, final long timeout)
throws MQClientException, RemotingException, InterruptedException {
final long beginStartTime = System.currentTimeMillis();
ExecutorService executor = this.getAsyncSenderExecutor();
@@ -1193,7 +1195,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public TransactionSendResult sendMessageInTransaction(final Message msg,
- final LocalTransactionExecuter localTransactionExecuter, final Object arg)
+ final LocalTransactionExecuter localTransactionExecuter, final Object arg)
throws MQClientException {
TransactionListener transactionListener = getCheckListener();
if (null == localTransactionExecuter && null == transactionListener) {
@@ -1330,7 +1332,8 @@ public class DefaultMQProducerImpl implements MQProducerInner {
return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null, timeout);
}
- public Message request(Message msg, long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException {
+ public Message request(Message msg,
+ long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException {
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1356,7 +1359,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
if (responseMessage == null) {
if (requestResponseFuture.isSendReqeustOk()) {
throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
- "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
+ "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
} else {
throw new MQClientException("send request message to <" + msg.getTopic() + "> fail", requestResponseFuture.getCause());
}
@@ -1394,8 +1397,8 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
- final long timeout) throws MQClientException, RemotingException, MQBrokerException,
- InterruptedException, RequestTimeoutException {
+ final long timeout) throws MQClientException, RemotingException, MQBrokerException,
+ InterruptedException, RequestTimeoutException {
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1421,7 +1424,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
if (responseMessage == null) {
if (requestResponseFuture.isSendReqeustOk()) {
throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
- "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
+ "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
} else {
throw new MQClientException("send request message to <" + msg.getTopic() + "> fail", requestResponseFuture.getCause());
}
@@ -1433,7 +1436,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public void request(final Message msg, final MessageQueueSelector selector, final Object arg,
- final RequestCallback requestCallback, final long timeout) throws RemotingException {
+ final RequestCallback requestCallback, final long timeout) throws RemotingException {
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1460,7 +1463,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public Message request(final Message msg, final MessageQueue mq, final long timeout)
- throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
+ throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1486,7 +1489,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
if (responseMessage == null) {
if (requestResponseFuture.isSendReqeustOk()) {
throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
- "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
+ "send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
} else {
throw new MQClientException("send request message to <" + msg.getTopic() + "> fail", requestResponseFuture.getCause());
}
@@ -1498,7 +1501,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
- throws RemotingException {
+ throws RemotingException {
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1537,7 +1540,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
}
- private void prepareSendRequest(final Message msg, long timeout){
+ private void prepareSendRequest(final Message msg, long timeout) {
String requestUniqId = RequestIdUtil.createUniqueRequestId();
String requestClientId = this.getmQClientFactory().getClientId();
MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REQUEST_UNIQ_ID, requestUniqId);
@@ -1556,11 +1559,13 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
}
- private SendResult reply(final Message msg, long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ private SendResult reply(final Message msg,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null, timeoutMillis);
}
- private SendResult reply(final Message msg, final SendCallback sendCallback, long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ private SendResult reply(final Message msg, final SendCallback sendCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
return this.sendDefaultImpl(msg, CommunicationMode.ASYNC, sendCallback, timeoutMillis);
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
index 4789c4d33e..bb017ef212 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
@@ -43,38 +43,29 @@ import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.exception.RemotingException;
/**
- * This class is the entry point for applications intending to send messages.
- *
+ * This class is the entry point for applications intending to send messages.
*
* It's fine to tune fields which exposes getter/setter methods, but keep in mind, all of them should work well out of
- * box for most scenarios.
- *
+ * box for most scenarios.
*
* This class aggregates various send methods to deliver messages to brokers. Each of them has pros and
- * cons; you'd better understand strengths and weakness of them before actually coding.
- *
+ * cons; you'd better understand strengths and weakness of them before actually coding.
*
- *
- * Thread Safety: After configuring and starting process, this class can be regarded as thread-safe
- * and used among multiple threads context.
- *
+ *
Thread Safety: After configuring and starting process, this class can be regarded as thread-safe
+ * and used among multiple threads context.
*/
public class DefaultMQProducer extends ClientConfig implements MQProducer {
- private final InternalLogger log = ClientLogger.getLog();
-
/**
* Wrapping internal implementations for virtually all methods presented in this class.
*/
protected final transient DefaultMQProducerImpl defaultMQProducerImpl;
-
+ private final InternalLogger log = ClientLogger.getLog();
/**
* Producer group conceptually aggregates all producer instances of exactly same role, which is particularly
- * important when transactional messages are involved.
- *
+ * important when transactional messages are involved.
*
- * For non-transactional messages, it does not matter as long as it's unique per process.
- *
+ * For non-transactional messages, it does not matter as long as it's unique per process.
*
* See {@linktourl http://rocketmq.apache.org/docs/core-concept/} for more discussion.
*/
@@ -101,16 +92,14 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
private int compressMsgBodyOverHowmuch = 1024 * 4;
/**
- * Maximum number of retry to perform internally before claiming sending failure in synchronous mode.
- *
+ * Maximum number of retry to perform internally before claiming sending failure in synchronous mode.
*
* This may potentially cause message duplication which is up to application developers to resolve.
*/
private int retryTimesWhenSendFailed = 2;
/**
- * Maximum number of retry to perform internally before claiming sending failure in asynchronous mode.
- *
+ * Maximum number of retry to perform internally before claiming sending failure in asynchronous mode.
*
* This may potentially cause message duplication which is up to application developers to resolve.
*/
@@ -269,14 +258,10 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
}
/**
- * Start this producer instance.
- *
+ * Start this producer instance.
*
- *
- * Much internal initializing procedures are carried out to make this instance prepared, thus, it's a must to invoke
- * this method before sending or querying messages.
- *
- *
+ * Much internal initializing procedures are carried out to make this instance prepared, thus, it's a must
+ * to invoke this method before sending or querying messages.
*
* @throws MQClientException if there is any unexpected error.
*/
@@ -317,8 +302,7 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
}
/**
- * Send message in synchronous mode. This method returns only when the sending procedure totally completes.
- *
+ * Send message in synchronous mode. This method returns only when the sending procedure totally completes.
*
* Warn: this method has internal retry-mechanism, that is, internal implementation will retry
* {@link #retryTimesWhenSendFailed} times before claiming failure. As a result, multiple messages may potentially
@@ -360,11 +344,9 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
}
/**
- * Send message to broker asynchronously.
- *
+ * Send message to broker asynchronously.
*
- * This method returns immediately. On sending completion, sendCallback will be executed.
- *
+ * This method returns immediately. On sending completion, sendCallback will be executed.
*
* Similar to {@link #send(Message)}, internal implementation would potentially retry up to {@link
* #retryTimesWhenSendAsyncFailed} times before claiming sending failure, which may yield message duplication and
@@ -584,7 +566,6 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
}
/**
- *
* @param msg
* @param timeout
* @return
@@ -595,13 +576,12 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
*/
@Override
public Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException,
- RemotingException, MQBrokerException, InterruptedException {
+ RemotingException, MQBrokerException, InterruptedException {
msg.setTopic(withNamespace(msg.getTopic()));
return this.defaultMQProducerImpl.request(msg, timeout);
}
/**
- *
* @param msg
* @param requestCallback
* @param timeout
@@ -612,12 +592,11 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
*/
@Override
public void request(final Message msg, final RequestCallback requestCallback, final long timeout)
- throws MQClientException, RemotingException, InterruptedException, MQBrokerException, RequestTimeoutException {
+ throws MQClientException, RemotingException, InterruptedException, MQBrokerException, RequestTimeoutException {
this.defaultMQProducerImpl.request(msg, requestCallback, timeout);
}
/**
- *
* @param msg
* @param selector
* @param arg
@@ -630,13 +609,12 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
*/
@Override
public Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
- final long timeout) throws MQClientException, RemotingException, MQBrokerException,
- InterruptedException, RequestTimeoutException {
+ final long timeout) throws MQClientException, RemotingException, MQBrokerException,
+ InterruptedException, RequestTimeoutException {
return this.defaultMQProducerImpl.request(msg, selector, arg, timeout);
}
/**
- *
* @param msg
* @param selector
* @param arg
@@ -649,13 +627,12 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
*/
@Override
public void request(final Message msg, final MessageQueueSelector selector, final Object arg,
- final RequestCallback requestCallback, final long timeout) throws MQClientException, RemotingException,
- InterruptedException {
+ final RequestCallback requestCallback, final long timeout) throws MQClientException, RemotingException,
+ InterruptedException {
this.defaultMQProducerImpl.request(msg, selector, arg, requestCallback, timeout);
}
/**
- *
* @param msg
* @param mq
* @param timeout
@@ -667,12 +644,11 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
*/
@Override
public Message request(final Message msg, final MessageQueue mq, final long timeout)
- throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
+ throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
return this.defaultMQProducerImpl.request(msg, mq, timeout);
}
/**
- *
* @param msg
* @param mq
* @param requestCallback
@@ -684,7 +660,7 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
*/
@Override
public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
- throws MQClientException, RemotingException, InterruptedException {
+ throws MQClientException, RemotingException, InterruptedException {
this.defaultMQProducerImpl.request(msg, mq, requestCallback, timeout);
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
index ce8d4a5024..a837c3d232 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/MQProducer.java
@@ -102,22 +102,23 @@ public interface MQProducer extends MQAdmin {
//for rpc
Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException,
- RemotingException, MQBrokerException, InterruptedException;
+ RemotingException, MQBrokerException, InterruptedException;
void request(final Message msg, final RequestCallback requestCallback, final long timeout)
- throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException, MQBrokerException;
+ throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException, MQBrokerException;
Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
- final long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException,
- InterruptedException;
+ final long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException,
+ InterruptedException;
void request(final Message msg, final MessageQueueSelector selector, final Object arg,
- final RequestCallback requestCallback, final long timeout) throws RequestTimeoutException, MQClientException, RemotingException,
- InterruptedException;
+ final RequestCallback requestCallback,
+ final long timeout) throws RequestTimeoutException, MQClientException, RemotingException,
+ InterruptedException;
Message request(final Message msg, final MessageQueue mq, final long timeout)
- throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException;
+ throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException;
void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
- throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException;
+ throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java
index 4a1874f929..3107ba57d6 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestCallback.java
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.rocketmq.client.producer;
import org.apache.rocketmq.common.message.Message;
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java
index 74195be33b..6ce53119ea 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestFutureTable.java
@@ -1,25 +1,41 @@
-package org.apache.rocketmq.client.producer;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-import org.apache.rocketmq.client.common.ClientErrorCode;
-import org.apache.rocketmq.client.exception.RequestTimeoutException;
-import org.apache.rocketmq.client.log.ClientLogger;
-import org.apache.rocketmq.logging.InternalLogger;
+package org.apache.rocketmq.client.producer;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import org.apache.rocketmq.client.common.ClientErrorCode;
+import org.apache.rocketmq.client.exception.RequestTimeoutException;
+import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.logging.InternalLogger;
public class RequestFutureTable {
private static InternalLogger log = ClientLogger.getLog();
private static ConcurrentHashMap requestFutureTable = new ConcurrentHashMap();
- public static ConcurrentHashMap getRequestFutureTable(){
+ public static ConcurrentHashMap getRequestFutureTable() {
return requestFutureTable;
}
- public static void scanExpiredRequest(){
+ public static void scanExpiredRequest() {
final List rfList = new LinkedList();
Iterator> it = requestFutureTable.entrySet().iterator();
while (it.hasNext()) {
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
index a5c5feebdb..d65b479434 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
@@ -1,32 +1,46 @@
-package org.apache.rocketmq.client.producer;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
-import org.apache.rocketmq.common.message.Message;
+package org.apache.rocketmq.client.producer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
+import org.apache.rocketmq.common.message.Message;
public class RequestResponseFuture {
private final String requestUniqId;
- private long timeoutMillis;
private final RequestCallback requestCallback;
private final long beginTimestamp = System.currentTimeMillis();
+ private final Message requestMsg = null;
+ private long timeoutMillis;
private CountDownLatch countDownLatch = new CountDownLatch(1);
-
private AtomicBoolean ececuteCallbackOnlyOnce = new AtomicBoolean(false);
private volatile Message responseMsg = null;
private volatile boolean sendReqeustOk = true;
private volatile Throwable cause = null;
- private final Message requestMsg = null;
-
- public RequestResponseFuture(String requestUniqId, long timeoutMillis, RequestCallback requestCallback){
+ public RequestResponseFuture(String requestUniqId, long timeoutMillis, RequestCallback requestCallback) {
this.requestUniqId = requestUniqId;
this.timeoutMillis = timeoutMillis;
this.requestCallback = requestCallback;
}
- public void executeRequestCallback(){
+ public void executeRequestCallback() {
if (requestCallback != null) {
if (sendReqeustOk && cause == null) {
requestCallback.onSuccess(responseMsg);
@@ -36,7 +50,7 @@ public class RequestResponseFuture {
}
}
- public boolean isTimeout(){
+ public boolean isTimeout() {
long diff = System.currentTimeMillis() - this.beginTimestamp;
return diff > this.timeoutMillis;
}
@@ -46,7 +60,7 @@ public class RequestResponseFuture {
return this.responseMsg;
}
- public void putResponseMessage(final Message responseMsg){
+ public void putResponseMessage(final Message responseMsg) {
this.responseMsg = responseMsg;
this.countDownLatch.countDown();
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
index ce41775227..62dd36dd61 100644
--- a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
+++ b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.rocketmq.client.utils;
import org.apache.rocketmq.common.MixAll;
diff --git a/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java b/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java
index c3613e7d4c..a7568f0a20 100644
--- a/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java
+++ b/common/src/main/java/org/apache/rocketmq/common/BrokerConfig.java
@@ -769,7 +769,7 @@ public class BrokerConfig {
public void setMsgTraceTopicName(String msgTraceTopicName) {
this.msgTraceTopicName = msgTraceTopicName;
}
-
+
public boolean isTraceTopicEnable() {
return traceTopicEnable;
}
diff --git a/common/src/main/java/org/apache/rocketmq/common/MixAll.java b/common/src/main/java/org/apache/rocketmq/common/MixAll.java
index a6151e55f7..0f7f0aa7ab 100644
--- a/common/src/main/java/org/apache/rocketmq/common/MixAll.java
+++ b/common/src/main/java/org/apache/rocketmq/common/MixAll.java
@@ -45,8 +45,6 @@ import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.logging.InternalLoggerFactory;
public class MixAll {
- private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME);
-
public static final String ROCKETMQ_HOME_ENV = "ROCKETMQ_HOME";
public static final String ROCKETMQ_HOME_PROPERTY = "rocketmq.home.dir";
public static final String NAMESRV_ADDR_ENV = "NAMESRV_ADDR";
@@ -74,30 +72,26 @@ public class MixAll {
public static final String CID_ONSAPI_OWNER_GROUP = "CID_ONSAPI_OWNER";
public static final String CID_ONSAPI_PULL_GROUP = "CID_ONSAPI_PULL";
public static final String CID_RMQ_SYS_PREFIX = "CID_RMQ_SYS_";
-
public static final List LOCAL_INET_ADDRESS = getLocalInetAddress();
public static final String LOCALHOST = localhost();
public static final String DEFAULT_CHARSET = "UTF-8";
public static final long MASTER_ID = 0L;
public static final long CURRENT_JVM_PID = getPID();
-
public static final String RETRY_GROUP_TOPIC_PREFIX = "%RETRY%";
-
public static final String DLQ_GROUP_TOPIC_PREFIX = "%DLQ%";
public static final String REPLY_TOPIC_POSTFIX = "REPLY_TOPIC";
public static final String SYSTEM_TOPIC_PREFIX = "rmq_sys_";
public static final String UNIQUE_MSG_QUERY_FLAG = "_UNIQUE_KEY_QUERY";
public static final String DEFAULT_TRACE_REGION_ID = "DefaultRegion";
public static final String CONSUME_CONTEXT_TYPE = "ConsumeContextType";
-
public static final String RMQ_SYS_TRANS_HALF_TOPIC = "RMQ_SYS_TRANS_HALF_TOPIC";
public static final String RMQ_SYS_TRACE_TOPIC = "RMQ_SYS_TRACE_TOPIC";
public static final String RMQ_SYS_TRANS_OP_HALF_TOPIC = "RMQ_SYS_TRANS_OP_HALF_TOPIC";
public static final String TRANS_CHECK_MAX_TIME_TOPIC = "TRANS_CHECK_MAX_TIME_TOPIC";
public static final String CID_SYS_RMQ_TRANS = "CID_RMQ_SYS_TRANS";
public static final String ACL_CONF_TOOLS_FILE = "/conf/tools.yml";
-
public static final String REPLY_MESSAGE_FLAG = "reply";
+ private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.COMMON_LOGGER_NAME);
public static String getWSAddr() {
String wsDomainName = System.getProperty("rocketmq.namesrv.domain", DEFAULT_NAMESRV_ADDR_LOOKUP);
diff --git a/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java b/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java
index 465baeae86..3bb09073f7 100644
--- a/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java
+++ b/common/src/main/java/org/apache/rocketmq/common/protocol/header/ReplyMessageRequestHeader.java
@@ -1,3 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.rocketmq.common.protocol.header;
import org.apache.rocketmq.remoting.CommandCustomHeader;
diff --git a/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java b/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java
index 9a58e5fdb6..86c5096df5 100644
--- a/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java
+++ b/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java
@@ -1,9 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package org.apache.rocketmq.common.utils;
import java.util.UUID;
public class RequestIdUtil {
- public static String createUniqueRequestId(){
+ public static String createUniqueRequestId() {
return UUID.randomUUID().toString();
}
}
From 1d3a5083a41bb7a6b53fa93b17cd63f9c0625726 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Wed, 28 Aug 2019 16:18:41 +0800
Subject: [PATCH 03/26] [RIP-16]fix test case error
---
.../org/apache/rocketmq/broker/client/ProducerManagerTest.java | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
index 08dbb9c754..c47a0cb7c6 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
@@ -20,6 +20,7 @@ import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import java.lang.reflect.Field;
import java.util.HashMap;
+import org.apache.rocketmq.remoting.protocol.LanguageCode;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -42,7 +43,7 @@ public class ProducerManagerTest {
@Before
public void init() {
producerManager = new ProducerManager();
- clientInfo = new ClientChannelInfo(channel);
+ clientInfo = new ClientChannelInfo(channel, "clientId", LanguageCode.JAVA, 0);
}
@Test
From 7e221e51e898a0d4f73d854409fa8b97f7778408 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Wed, 11 Sep 2019 19:40:04 +0800
Subject: [PATCH 04/26] add example of request-response model
---
.../rocketmq/client/utils/MessageUtil.java | 22 ++---
.../example/rpc/AsyncRequestProducer.java | 64 ++++++++++++++
.../rocketmq/example/rpc/RequestProducer.java | 54 ++++++++++++
.../example/rpc/ResponseConsumer.java | 83 +++++++++++++++++++
4 files changed, 212 insertions(+), 11 deletions(-)
create mode 100644 example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java
create mode 100644 example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
create mode 100644 example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
diff --git a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
index 62dd36dd61..81da669ff8 100644
--- a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
+++ b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
@@ -17,31 +17,31 @@
package org.apache.rocketmq.client.utils;
+import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
public class MessageUtil {
- public static Message createReplyMessage(final Message requestMessage) {
+ public static Message createReplyMessage(final Message requestMessage) throws MQClientException {
if (requestMessage != null) {
Message replyMessage = new Message();
String cluster = requestMessage.getProperty(MessageConst.PROPERTY_CLUSTER);
String replyTo = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
String requestUniqId = requestMessage.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
String ttl = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_TTL);
- if (cluster == null) {
+ if (cluster != null) {
+ String replyTopic = MixAll.getReplyTopic(cluster);
+ replyMessage.setTopic(replyTopic);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TYPE, MixAll.REPLY_MESSAGE_FLAG);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_REQUEST_UNIQ_ID, requestUniqId);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_REPLY_TO, replyTo);
+ MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TTL, ttl);
+ return replyMessage;
}
- String replyTopic = MixAll.getReplyTopic(cluster);
- replyMessage.setTopic(replyTopic);
- MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TYPE, MixAll.REPLY_MESSAGE_FLAG);
- MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_REQUEST_UNIQ_ID, requestUniqId);
- MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_REPLY_TO, replyTo);
- MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TTL, ttl);
-
- return replyMessage;
}
- return null;
+ throw new MQClientException(-1, "create reply message fail.");
}
}
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java
new file mode 100644
index 0000000000..d2475c165b
--- /dev/null
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.example.rpc;
+
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.client.producer.RequestCallback;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+
+public class AsyncRequestProducer {
+ private static final InternalLogger log = ClientLogger.getLog();
+
+ public static void main(String[] args) throws MQClientException, InterruptedException {
+ String producerGroup = "ProducerGroup-Name";
+ String namesrvAddr = "10.255.2.37:9876;10.255.2.37:9875";
+ String topic = "RequestTopic";
+ long ttl = 3000;
+
+ DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
+ producer.setNamesrvAddr(namesrvAddr);
+ producer.start();
+
+ try {
+ Message msg = new Message(topic,
+ "",
+ "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
+
+ long begin = System.currentTimeMillis();
+ producer.request(msg, new RequestCallback() {
+ @Override
+ public void onSuccess(Message message) {
+ long cost = System.currentTimeMillis() - begin;
+ System.out.printf("request to <%s> cost: %d replyMessage: %s %n", topic, cost, message);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ System.err.printf("request to <%s> fail.", topic);
+ }
+ }, ttl);
+ } catch (Exception e) {
+ log.warn("", e);
+ }
+// producer.shutdown();
+ }
+}
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
new file mode 100644
index 0000000000..73397738d5
--- /dev/null
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.example.rpc;
+
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.DefaultMQProducer;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.remoting.common.RemotingHelper;
+
+public class RequestProducer {
+ private static final InternalLogger log = ClientLogger.getLog();
+
+ public static void main(String[] args) throws MQClientException, InterruptedException {
+ String producerGroup = "ProducerGroup-Name";
+ String namesrvAddr = "10.255.2.37:9876;10.255.2.37:9875";
+ String topic = "RequestTopic";
+ long ttl = 3000;
+
+ DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
+ producer.setNamesrvAddr(namesrvAddr);
+ producer.start();
+
+ try {
+ Message msg = new Message(topic,
+ "",
+ "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
+
+ long begin = System.currentTimeMillis();
+ Message retMsg = producer.request(msg, ttl);
+ long cost = System.currentTimeMillis() - begin;
+ System.err.printf("request to <%s> cost: %d replyMessage: %s %n", topic, cost, retMsg);
+ } catch (Exception e) {
+ log.warn("", e);
+ }
+ producer.shutdown();
+ }
+}
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
new file mode 100644
index 0000000000..ff3652fe3a
--- /dev/null
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.example.rpc;
+
+import java.util.List;
+import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
+import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
+import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
+import org.apache.rocketmq.client.exception.MQBrokerException;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.utils.MessageUtil;
+import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.remoting.exception.RemotingException;
+
+public class ResponseConsumer {
+ private static final InternalLogger log = ClientLogger.getLog();
+
+ public static void main(String[] args) throws InterruptedException, MQClientException {
+ String consumerGroup = "ConsumeGroup-Name";
+ String namesrvAddr = "10.255.2.37:9873";
+ String topic = "RequestTopic";
+
+ DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
+ consumer.setNamesrvAddr(namesrvAddr);
+ consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
+
+ consumer.registerMessageListener(new MessageListenerConcurrently() {
+ @Override
+ public ConsumeConcurrentlyStatus consumeMessage(List msgs, ConsumeConcurrentlyContext context) {
+ System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
+ for (MessageExt msg : msgs) {
+ try {
+ log.info("handle message: {} body={}", msg, new String(msg.getBody()));
+ String replyTo = msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
+
+ //You must use MessageUtil to creage reply message, otherwise reply message maybe wrong.
+ Message replyMessage = MessageUtil.createReplyMessage(msg);
+ replyMessage.setBody("reply message contents.".getBytes());
+
+ //maybe you should create a producer to send reply message.
+ SendResult sendResult = consumer.getDefaultMQPushConsumerImpl().getmQClientFactory().getDefaultMQProducer().send(replyMessage, 3000);
+ System.out.printf("reply msg %s to %s , %s %n", replyMessage.toString(), replyTo, sendResult.toString());
+ } catch (MQClientException e) {
+ e.printStackTrace();
+ } catch (RemotingException e) {
+ e.printStackTrace();
+ } catch (MQBrokerException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
+ }
+ });
+
+ consumer.subscribe(topic, "*");
+ consumer.start();
+ System.out.printf("Consumer Started.%n");
+ }
+}
From cc0a5e391ea90e37936b7ba63b8c273f8cbcc660 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Wed, 11 Sep 2019 19:47:47 +0800
Subject: [PATCH 05/26] code format
---
.../rocketmq/example/rpc/RequestProducer.java | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
index 73397738d5..a83f1db87f 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
@@ -38,14 +38,14 @@ public class RequestProducer {
producer.start();
try {
- Message msg = new Message(topic,
- "",
- "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
+ Message msg = new Message(topic,
+ "",
+ "Hello world".getBytes(RemotingHelper.DEFAULT_CHARSET));
- long begin = System.currentTimeMillis();
- Message retMsg = producer.request(msg, ttl);
- long cost = System.currentTimeMillis() - begin;
- System.err.printf("request to <%s> cost: %d replyMessage: %s %n", topic, cost, retMsg);
+ long begin = System.currentTimeMillis();
+ Message retMsg = producer.request(msg, ttl);
+ long cost = System.currentTimeMillis() - begin;
+ System.err.printf("request to <%s> cost: %d replyMessage: %s %n", topic, cost, retMsg);
} catch (Exception e) {
log.warn("", e);
}
From 53a6955e5b3945b2783fdc58900fca116410f505 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Thu, 12 Sep 2019 10:40:21 +0800
Subject: [PATCH 06/26] [RIP-16]change the way creating reply message
---
.../java/org/apache/rocketmq/client/utils/MessageUtil.java | 3 ++-
.../org/apache/rocketmq/example/rpc/ResponseConsumer.java | 4 ++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
index 81da669ff8..e60c0f665f 100644
--- a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
+++ b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
@@ -24,13 +24,14 @@ import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
public class MessageUtil {
- public static Message createReplyMessage(final Message requestMessage) throws MQClientException {
+ public static Message createReplyMessage(final Message requestMessage, final byte[] body) throws MQClientException {
if (requestMessage != null) {
Message replyMessage = new Message();
String cluster = requestMessage.getProperty(MessageConst.PROPERTY_CLUSTER);
String replyTo = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
String requestUniqId = requestMessage.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
String ttl = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_TTL);
+ replyMessage.setBody(body);
if (cluster != null) {
String replyTopic = MixAll.getReplyTopic(cluster);
replyMessage.setTopic(replyTopic);
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
index ff3652fe3a..3580f87fb5 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
@@ -56,8 +56,8 @@ public class ResponseConsumer {
String replyTo = msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
//You must use MessageUtil to creage reply message, otherwise reply message maybe wrong.
- Message replyMessage = MessageUtil.createReplyMessage(msg);
- replyMessage.setBody("reply message contents.".getBytes());
+ byte[] replyContent = "reply message contents.".getBytes();
+ Message replyMessage = MessageUtil.createReplyMessage(msg, replyContent);
//maybe you should create a producer to send reply message.
SendResult sendResult = consumer.getDefaultMQPushConsumerImpl().getmQClientFactory().getDefaultMQProducer().send(replyMessage, 3000);
From ec1f9266d2bcd95c9ac41e049d15fec20c9d4afa Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Wed, 18 Sep 2019 10:48:15 +0800
Subject: [PATCH 07/26] optimize request/response examples
---
.../apache/rocketmq/example/rpc/AsyncRequestProducer.java | 5 ++---
.../org/apache/rocketmq/example/rpc/RequestProducer.java | 4 +---
.../org/apache/rocketmq/example/rpc/ResponseConsumer.java | 4 +---
3 files changed, 4 insertions(+), 9 deletions(-)
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java
index d2475c165b..072291d5c2 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/AsyncRequestProducer.java
@@ -29,13 +29,11 @@ public class AsyncRequestProducer {
private static final InternalLogger log = ClientLogger.getLog();
public static void main(String[] args) throws MQClientException, InterruptedException {
- String producerGroup = "ProducerGroup-Name";
- String namesrvAddr = "10.255.2.37:9876;10.255.2.37:9875";
+ String producerGroup = "please_rename_unique_group_name";
String topic = "RequestTopic";
long ttl = 3000;
DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
- producer.setNamesrvAddr(namesrvAddr);
producer.start();
try {
@@ -59,6 +57,7 @@ public class AsyncRequestProducer {
} catch (Exception e) {
log.warn("", e);
}
+ /* shutdown after your request callback is finished */
// producer.shutdown();
}
}
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
index a83f1db87f..b038151a88 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
@@ -28,13 +28,11 @@ public class RequestProducer {
private static final InternalLogger log = ClientLogger.getLog();
public static void main(String[] args) throws MQClientException, InterruptedException {
- String producerGroup = "ProducerGroup-Name";
- String namesrvAddr = "10.255.2.37:9876;10.255.2.37:9875";
+ String producerGroup = "please_rename_unique_group_name";
String topic = "RequestTopic";
long ttl = 3000;
DefaultMQProducer producer = new DefaultMQProducer(producerGroup);
- producer.setNamesrvAddr(namesrvAddr);
producer.start();
try {
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
index 3580f87fb5..131fc9dfcc 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
@@ -38,12 +38,10 @@ public class ResponseConsumer {
private static final InternalLogger log = ClientLogger.getLog();
public static void main(String[] args) throws InterruptedException, MQClientException {
- String consumerGroup = "ConsumeGroup-Name";
- String namesrvAddr = "10.255.2.37:9873";
+ String consumerGroup = "please_rename_unique_group_name";
String topic = "RequestTopic";
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
- consumer.setNamesrvAddr(namesrvAddr);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
consumer.registerMessageListener(new MessageListenerConcurrently() {
From 5e1732a9c4063f4b299684e172409f74256bd5c2 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Wed, 18 Sep 2019 15:00:05 +0800
Subject: [PATCH 08/26] add unittest of request/response pattern
---
.../processor/ReplyMessageProcessorTest.java | 141 ++++++++++++++++++
.../client/impl/MQClientAPIImplTest.java | 36 ++++-
.../producer/DefaultMQProducerTest.java | 111 +++++++++++++-
.../producer/RequestResponseFutureTest.java | 45 ++++++
.../client/utils/MessageUtilsTest.java | 62 ++++++++
5 files changed, 388 insertions(+), 7 deletions(-)
create mode 100644 broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
create mode 100644 client/src/test/java/org/apache/rocketmq/client/producer/RequestResponseFutureTest.java
create mode 100644 client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java b/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
new file mode 100644
index 0000000000..f48594ebbe
--- /dev/null
+++ b/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.rocketmq.broker.processor;
+
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import java.lang.reflect.Field;
+import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.rocketmq.broker.BrokerController;
+import org.apache.rocketmq.broker.client.ClientChannelInfo;
+import org.apache.rocketmq.broker.client.net.Broker2Client;
+import org.apache.rocketmq.broker.transaction.TransactionalMessageService;
+import org.apache.rocketmq.common.BrokerConfig;
+import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.apache.rocketmq.common.message.MessageDecoder;
+import org.apache.rocketmq.common.message.MessageExt;
+import org.apache.rocketmq.common.protocol.RequestCode;
+import org.apache.rocketmq.common.protocol.ResponseCode;
+import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader;
+import org.apache.rocketmq.remoting.exception.RemotingCommandException;
+import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
+import org.apache.rocketmq.remoting.exception.RemotingTimeoutException;
+import org.apache.rocketmq.remoting.netty.NettyClientConfig;
+import org.apache.rocketmq.remoting.netty.NettyServerConfig;
+import org.apache.rocketmq.remoting.protocol.LanguageCode;
+import org.apache.rocketmq.remoting.protocol.RemotingCommand;
+import org.apache.rocketmq.store.AppendMessageResult;
+import org.apache.rocketmq.store.AppendMessageStatus;
+import org.apache.rocketmq.store.MessageExtBrokerInner;
+import org.apache.rocketmq.store.MessageStore;
+import org.apache.rocketmq.store.PutMessageResult;
+import org.apache.rocketmq.store.PutMessageStatus;
+import org.apache.rocketmq.store.config.MessageStoreConfig;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ReplyMessageProcessorTest {
+ private ReplyMessageProcessor replyMessageProcessor;
+ @Spy
+ private BrokerController brokerController = new BrokerController(new BrokerConfig(), new NettyServerConfig(), new NettyClientConfig(), new MessageStoreConfig());
+ @Mock
+ private ChannelHandlerContext handlerContext;
+ @Mock
+ private MessageStore messageStore;
+ @Mock
+ private Channel channel;
+ @Mock
+ private TransactionalMessageService transactionMsgService;
+ private String topic = "FooBar";
+ private String group = "FooBarGroup";
+ private ClientChannelInfo clientInfo;
+ @Mock
+ private Broker2Client broker2Client;
+
+ @Before
+ public void init() throws IllegalAccessException, NoSuchFieldException {
+ clientInfo = new ClientChannelInfo(channel, "127.0.0.1", LanguageCode.JAVA, 0);
+ brokerController.setMessageStore(messageStore);
+ Field field = BrokerController.class.getDeclaredField("broker2Client");
+ field.setAccessible(true);
+ field.set(brokerController, broker2Client);
+ when(messageStore.now()).thenReturn(System.currentTimeMillis());
+ Channel mockChannel = mock(Channel.class);
+ when(mockChannel.remoteAddress()).thenReturn(new InetSocketAddress(1024));
+ when(handlerContext.channel()).thenReturn(mockChannel);
+ when(messageStore.lookMessageByOffset(anyLong())).thenReturn(new MessageExt());
+ replyMessageProcessor = new ReplyMessageProcessor(brokerController);
+ }
+
+ @Test
+ public void testProcessRequest_Success() throws RemotingCommandException, InterruptedException, RemotingTimeoutException, RemotingSendRequestException {
+ when(messageStore.putMessage(any(MessageExtBrokerInner.class))).thenReturn(new PutMessageResult(PutMessageStatus.PUT_OK, new AppendMessageResult(AppendMessageStatus.PUT_OK)));
+ brokerController.getProducerManager().registerProducer(group, clientInfo);
+ final RemotingCommand request = createSendMessageRequestHeaderCommand(RequestCode.SEND_REPLY_MESSAGE);
+ when(brokerController.getBroker2Client().callClient(any(Channel.class), any(RemotingCommand.class))).thenReturn(createResponse(ResponseCode.SUCCESS, request));
+ RemotingCommand responseToReturn = replyMessageProcessor.processRequest(handlerContext, request);
+ assertThat(responseToReturn.getCode()).isEqualTo(ResponseCode.SUCCESS);
+ assertThat(responseToReturn.getOpaque()).isEqualTo(request.getOpaque());
+ }
+
+ private RemotingCommand createSendMessageRequestHeaderCommand(int requestCode) {
+ SendMessageRequestHeader requestHeader = createSendMessageRequestHeader();
+ RemotingCommand request = RemotingCommand.createRequestCommand(requestCode, requestHeader);
+ request.setBody(new byte[] {'a'});
+ request.makeCustomHeaderToNet();
+ return request;
+ }
+
+ private SendMessageRequestHeader createSendMessageRequestHeader() {
+ SendMessageRequestHeader requestHeader = new SendMessageRequestHeader();
+ requestHeader.setProducerGroup(group);
+ requestHeader.setTopic(topic);
+ requestHeader.setDefaultTopic(MixAll.AUTO_CREATE_TOPIC_KEY_TOPIC);
+ requestHeader.setDefaultTopicQueueNums(3);
+ requestHeader.setQueueId(1);
+ requestHeader.setSysFlag(0);
+ requestHeader.setBornTimestamp(System.currentTimeMillis());
+ requestHeader.setFlag(124);
+ requestHeader.setReconsumeTimes(0);
+ Map map = new HashMap();
+ map.put(MessageConst.PROPERTY_MESSAGE_REPLY_TO, "127.0.0.1");
+ requestHeader.setProperties(MessageDecoder.messageProperties2String(map));
+ return requestHeader;
+ }
+
+ private RemotingCommand createResponse(int code, RemotingCommand request) {
+ RemotingCommand response = RemotingCommand.createResponseCommand(SendMessageResponseHeader.class);
+ response.setCode(code);
+ response.setOpaque(request.getOpaque());
+ return response;
+ }
+}
\ No newline at end of file
diff --git a/client/src/test/java/org/apache/rocketmq/client/impl/MQClientAPIImplTest.java b/client/src/test/java/org/apache/rocketmq/client/impl/MQClientAPIImplTest.java
index 84af632355..3f00d9e403 100644
--- a/client/src/test/java/org/apache/rocketmq/client/impl/MQClientAPIImplTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/impl/MQClientAPIImplTest.java
@@ -42,6 +42,7 @@ import org.apache.rocketmq.remoting.protocol.RemotingCommand;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.junit.MockitoJUnitRunner;
@@ -164,7 +165,7 @@ public class MQClientAPIImplTest {
public Object answer(InvocationOnMock mock) throws Throwable {
InvokeCallback callback = mock.getArgument(3);
RemotingCommand request = mock.getArgument(1);
- ResponseFuture responseFuture = new ResponseFuture(null,request.getOpaque(), 3 * 1000, null, null);
+ ResponseFuture responseFuture = new ResponseFuture(null, request.getOpaque(), 3 * 1000, null, null);
responseFuture.setResponseCommand(createSuccessResponse(request));
callback.operationComplete(responseFuture);
return null;
@@ -289,6 +290,7 @@ public class MQClientAPIImplTest {
assertThat(ex.getErrorMessage()).isEqualTo("corresponding to accessConfig has been deleted failed");
}
}
+
@Test
public void testResumeCheckHalfMessage_WithException() throws RemotingException, InterruptedException, MQBrokerException, MQClientException {
doAnswer(new Answer() {
@@ -322,6 +324,38 @@ public class MQClientAPIImplTest {
assertThat(result).isEqualTo(true);
}
+ @Test
+ public void testSendMessageTypeofReply() throws Exception {
+ doAnswer(new Answer() {
+ @Override
+ public Object answer(InvocationOnMock mock) throws Throwable {
+ InvokeCallback callback = mock.getArgument(3);
+ RemotingCommand request = mock.getArgument(1);
+ ResponseFuture responseFuture = new ResponseFuture(null, request.getOpaque(), 3 * 1000, null, null);
+ responseFuture.setResponseCommand(createSuccessResponse(request));
+ callback.operationComplete(responseFuture);
+ return null;
+ }
+ }).when(remotingClient).invokeAsync(Matchers.anyString(), Matchers.any(RemotingCommand.class), Matchers.anyLong(), Matchers.any(InvokeCallback.class));
+ SendMessageContext sendMessageContext = new SendMessageContext();
+ sendMessageContext.setProducer(new DefaultMQProducerImpl(new DefaultMQProducer()));
+ msg.getProperties().put("MSG_TYPE", "reply");
+ mqClientAPI.sendMessage(brokerAddr, brokerName, msg, new SendMessageRequestHeader(), 3 * 1000, CommunicationMode.ASYNC,
+ new SendCallback() {
+ @Override
+ public void onSuccess(SendResult sendResult) {
+ assertThat(sendResult.getSendStatus()).isEqualTo(SendStatus.SEND_OK);
+ assertThat(sendResult.getOffsetMsgId()).isEqualTo("123");
+ assertThat(sendResult.getQueueOffset()).isEqualTo(123L);
+ assertThat(sendResult.getMessageQueue().getQueueId()).isEqualTo(1);
+ }
+
+ @Override
+ public void onException(Throwable e) {
+ }
+ }, null, null, 0, sendMessageContext, defaultMQProducerImpl);
+ }
+
private RemotingCommand createResumeSuccessResponse(RemotingCommand request) {
RemotingCommand response = RemotingCommand.createResponseCommand(null);
response.setCode(ResponseCode.SUCCESS);
diff --git a/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java b/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java
index 9540755fe3..6f2f959632 100644
--- a/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java
@@ -21,6 +21,8 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@@ -30,6 +32,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.exception.RequestTimeoutException;
import org.apache.rocketmq.client.hook.SendMessageContext;
import org.apache.rocketmq.client.hook.SendMessageHook;
import org.apache.rocketmq.client.impl.CommunicationMode;
@@ -45,6 +48,7 @@ import org.apache.rocketmq.common.protocol.route.BrokerData;
import org.apache.rocketmq.common.protocol.route.QueueData;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.remoting.exception.RemotingException;
+import org.apache.rocketmq.remoting.exception.RemotingSendRequestException;
import org.apache.rocketmq.remoting.netty.NettyRemotingClient;
import org.junit.After;
import org.junit.Before;
@@ -184,6 +188,7 @@ public class DefaultMQProducerTest {
});
countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
}
+
@Test
public void testSendMessageAsync() throws RemotingException, MQClientException, InterruptedException {
final AtomicInteger cc = new AtomicInteger(0);
@@ -211,12 +216,12 @@ public class DefaultMQProducerTest {
Message message = new Message();
message.setTopic("test");
message.setBody("hello world".getBytes());
- producer.send(new Message(),sendCallback);
- producer.send(message,sendCallback,1000);
- producer.send(message,new MessageQueue(),sendCallback);
- producer.send(new Message(),new MessageQueue(),sendCallback,1000);
- producer.send(new Message(),messageQueueSelector,null,sendCallback);
- producer.send(message,messageQueueSelector,null,sendCallback,1000);
+ producer.send(new Message(), sendCallback);
+ producer.send(message, sendCallback, 1000);
+ producer.send(message, new MessageQueue(), sendCallback);
+ producer.send(new Message(), new MessageQueue(), sendCallback, 1000);
+ producer.send(new Message(), messageQueueSelector, null, sendCallback);
+ producer.send(message, messageQueueSelector, null, sendCallback, 1000);
countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
assertThat(cc.get()).isEqualTo(6);
@@ -311,6 +316,100 @@ public class DefaultMQProducerTest {
assertThat(remotingClient.getCallbackExecutor()).isEqualTo(customized);
}
+ @Test
+ public void testRequestMessage() throws RemotingException, RequestTimeoutException, MQClientException, InterruptedException, MQBrokerException {
+ when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
+ new Thread(new Runnable() {
+ @Override public void run() {
+ boolean flag = true;
+ ConcurrentHashMap responseMap = null;
+ while (flag) {
+ responseMap = RequestFutureTable.getRequestFutureTable();
+ if (responseMap != null) {
+ flag = false;
+ }
+ }
+ assertThat(responseMap).isNotNull();
+ for (Map.Entry entry : responseMap.entrySet()) {
+ RequestResponseFuture future = entry.getValue();
+ future.putResponseMessage(message);
+ }
+ }
+ }).start();
+ Message result = producer.request(message, 3 * 1000L);
+ assertThat(result.getTopic()).isEqualTo("FooBar");
+ assertThat(result.getBody()).isEqualTo(new byte[] {'a'});
+ }
+
+ @Test(expected = RequestTimeoutException.class)
+ public void testRequestMessage_RequestTimeoutException() throws RemotingException, RequestTimeoutException, MQClientException, InterruptedException, MQBrokerException {
+ when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
+ Message result = producer.request(message, 3 * 1000L);
+ }
+
+ @Test
+ public void testAsyncRequest_OnSuccess() throws Exception {
+ when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ RequestCallback requestCallback = new RequestCallback() {
+ @Override public void onSuccess(Message message) {
+ assertThat(message.getTopic()).isEqualTo("FooBar");
+ assertThat(message.getBody()).isEqualTo(new byte[] {'a'});
+ assertThat(message.getFlag()).isEqualTo(1);
+ countDownLatch.countDown();
+ }
+
+ @Override public void onException(Throwable e) {
+ }
+ };
+ producer.request(message, requestCallback, 3 * 1000L);
+ ConcurrentHashMap responseMap = RequestFutureTable.getRequestFutureTable();
+ assertThat(responseMap).isNotNull();
+ for (Map.Entry entry : responseMap.entrySet()) {
+ RequestResponseFuture future = entry.getValue();
+ future.setSendReqeustOk(true);
+ message.setFlag(1);
+ future.getRequestCallback().onSuccess(message);
+ }
+ countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
+ }
+
+ @Test
+ public void testAsyncRequest_OnException() throws Exception {
+ final AtomicInteger cc = new AtomicInteger(0);
+ final CountDownLatch countDownLatch = new CountDownLatch(1);
+ RequestCallback requestCallback = new RequestCallback() {
+ @Override public void onSuccess(Message message) {
+
+ }
+
+ @Override public void onException(Throwable e) {
+ cc.incrementAndGet();
+ countDownLatch.countDown();
+ }
+ };
+ MessageQueueSelector messageQueueSelector = new MessageQueueSelector() {
+ @Override
+ public MessageQueue select(List mqs, Message msg, Object arg) {
+ return null;
+ }
+ };
+
+ try {
+ producer.request(message, requestCallback, 3 * 1000L);
+ failBecauseExceptionWasNotThrown(RemotingSendRequestException.class);
+ } catch (RemotingSendRequestException e) {
+ ConcurrentHashMap responseMap = RequestFutureTable.getRequestFutureTable();
+ assertThat(responseMap).isNotNull();
+ for (Map.Entry entry : responseMap.entrySet()) {
+ RequestResponseFuture future = entry.getValue();
+ future.getRequestCallback().onException(new Throwable());
+ }
+ }
+ countDownLatch.await(3000L, TimeUnit.MILLISECONDS);
+ assertThat(cc.get()).isEqualTo(1);
+ }
+
public static TopicRouteData createTopicRoute() {
TopicRouteData topicRouteData = new TopicRouteData();
diff --git a/client/src/test/java/org/apache/rocketmq/client/producer/RequestResponseFutureTest.java b/client/src/test/java/org/apache/rocketmq/client/producer/RequestResponseFutureTest.java
new file mode 100644
index 0000000000..90e4623e9b
--- /dev/null
+++ b/client/src/test/java/org/apache/rocketmq/client/producer/RequestResponseFutureTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.client.producer;
+
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.rocketmq.common.message.Message;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RequestResponseFutureTest {
+
+ @Test
+ public void testExecuteRequestCallback() throws Exception {
+ final AtomicInteger cc = new AtomicInteger(0);
+ RequestResponseFuture future = new RequestResponseFuture(UUID.randomUUID().toString(), 3 * 1000L, new RequestCallback() {
+ @Override public void onSuccess(Message message) {
+ cc.incrementAndGet();
+ }
+
+ @Override public void onException(Throwable e) {
+ }
+ });
+ future.setSendReqeustOk(true);
+ future.executeRequestCallback();
+ assertThat(cc.get()).isEqualTo(1);
+ }
+
+}
diff --git a/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java b/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java
new file mode 100644
index 0000000000..a722fa6cbb
--- /dev/null
+++ b/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.rocketmq.client.utils;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageAccessor;
+import org.apache.rocketmq.common.message.MessageConst;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
+
+public class MessageUtilsTest {
+
+ @Test
+ public void testCreateReplyMessage() throws MQClientException {
+ Message msg = MessageUtil.createReplyMessage(createReplyMessage("clusterName"), new byte[] {'a'});
+ assertThat(msg.getTopic()).isEqualTo("clusterName" + "_" + MixAll.REPLY_TOPIC_POSTFIX);
+ assertThat(msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO)).isEqualTo("127.0.0.1");
+ assertThat(msg.getProperty(MessageConst.PROPERTY_MESSAGE_TTL)).isEqualTo("3000");
+ }
+
+ @Test
+ public void testCreateReplyMessage_Exception() throws MQClientException {
+ try {
+ Message msg = MessageUtil.createReplyMessage(createReplyMessage(null), new byte[] {'a'});
+ failBecauseExceptionWasNotThrown(MQClientException.class);
+ } catch (MQClientException e) {
+ assertThat(e).hasMessageContaining("create reply message fail.");
+ }
+ }
+
+ private Message createReplyMessage(String clusterName) {
+ Message requestMessage = new Message();
+ Map map = new HashMap();
+ map.put(MessageConst.PROPERTY_MESSAGE_REPLY_TO, "127.0.0.1");
+ map.put(MessageConst.PROPERTY_CLUSTER, clusterName);
+ map.put(MessageConst.PROPERTY_MESSAGE_TTL, "3000");
+ MessageAccessor.setProperties(requestMessage, map);
+ return requestMessage;
+ }
+
+}
From 4c4bf104b5f898a0263f2effd22ac9e652cf36fd Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Sat, 21 Sep 2019 23:18:53 +0800
Subject: [PATCH 09/26] add unittest of request/response pattern
---
.../broker/client/ProducerManagerTest.java | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java b/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
index c47a0cb7c6..6271138313 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/client/ProducerManagerTest.java
@@ -50,7 +50,7 @@ public class ProducerManagerTest {
public void scanNotActiveChannel() throws Exception {
producerManager.registerProducer(group, clientInfo);
assertThat(producerManager.getGroupChannelTable().get(group).get(channel)).isNotNull();
-
+ assertThat(producerManager.findChannel("clientId")).isNotNull();
Field field = ProducerManager.class.getDeclaredField("CHANNEL_EXPIRED_TIMEOUT");
field.setAccessible(true);
long CHANNEL_EXPIRED_TIMEOUT = field.getLong(producerManager);
@@ -58,22 +58,28 @@ public class ProducerManagerTest {
when(channel.close()).thenReturn(mock(ChannelFuture.class));
producerManager.scanNotActiveChannel();
assertThat(producerManager.getGroupChannelTable().get(group).get(channel)).isNull();
+ assertThat(producerManager.findChannel("clientId")).isNull();
}
@Test
public void doChannelCloseEvent() throws Exception {
producerManager.registerProducer(group, clientInfo);
assertThat(producerManager.getGroupChannelTable().get(group).get(channel)).isNotNull();
+ assertThat(producerManager.findChannel("clientId")).isNotNull();
producerManager.doChannelCloseEvent("127.0.0.1", channel);
assertThat(producerManager.getGroupChannelTable().get(group).get(channel)).isNull();
+ assertThat(producerManager.findChannel("clientId")).isNull();
}
@Test
public void testRegisterProducer() throws Exception {
producerManager.registerProducer(group, clientInfo);
HashMap channelMap = producerManager.getGroupChannelTable().get(group);
+ Channel channel1 = producerManager.findChannel("clientId");
assertThat(channelMap).isNotNull();
+ assertThat(channel1).isNotNull();
assertThat(channelMap.get(channel)).isEqualTo(clientInfo);
+ assertThat(channel1).isEqualTo(channel);
}
@Test
@@ -82,10 +88,15 @@ public class ProducerManagerTest {
HashMap channelMap = producerManager.getGroupChannelTable().get(group);
assertThat(channelMap).isNotNull();
assertThat(channelMap.get(channel)).isEqualTo(clientInfo);
-
+ Channel channel1 = producerManager.findChannel("clientId");
+ assertThat(channel1).isNotNull();
+ assertThat(channel1).isEqualTo(channel);
producerManager.unregisterProducer(group, clientInfo);
channelMap = producerManager.getGroupChannelTable().get(group);
+ channel1 = producerManager.findChannel("clientId");
assertThat(channelMap).isNull();
+ assertThat(channel1).isNull();
+
}
}
\ No newline at end of file
From 28936fa12a21b13e9d5813385c6d59727d27b839 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Mon, 23 Sep 2019 20:07:41 +0800
Subject: [PATCH 10/26] add reply interface to consumer
---
.../consumer/DefaultMQPullConsumer.java | 49 ++++++++
.../consumer/DefaultMQPushConsumer.java | 49 ++++++++
.../client/impl/ClientRemotingProcessor.java | 7 +-
.../consumer/DefaultMQPullConsumerImpl.java | 24 ++++
.../consumer/DefaultMQPushConsumerImpl.java | 29 ++++-
.../client/impl/consumer/MQConsumerInner.java | 15 +++
.../impl/producer/DefaultMQProducerImpl.java | 50 ++++----
.../client/producer/DefaultMQProducer.java | 118 +++++++++++-------
.../producer/RequestResponseFuture.java | 20 +--
.../rocketmq/client/utils/MessageUtil.java | 4 +-
.../rocketmq/example/rpc/RequestProducer.java | 8 +-
.../example/rpc/ResponseConsumer.java | 24 +---
12 files changed, 275 insertions(+), 122 deletions(-)
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPullConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPullConsumer.java
index f3b6caaa71..17e60080e0 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPullConsumer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPullConsumer.java
@@ -25,7 +25,10 @@ import org.apache.rocketmq.client.consumer.store.OffsetStore;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.consumer.DefaultMQPullConsumerImpl;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
@@ -444,4 +447,50 @@ public class DefaultMQPullConsumer extends ClientConfig implements MQPullConsume
public void setMaxReconsumeTimes(final int maxReconsumeTimes) {
this.maxReconsumeTimes = maxReconsumeTimes;
}
+
+ /**
+ * send a reply message to the producer of the original request message
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @param timeoutMillis
+ * @return {@link SendResult} instance to inform senders details of the deliverable, say Message ID of the message,
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ return this.defaultMQPullConsumerImpl.reply(requestMsg, replyContent, timeoutMillis);
+ }
+
+ /**
+ * send a reply message to the producer of the original request message asynchronously
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @param replyCallback callback to execute on replying completion.
+ * @param timeoutMillis
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public void reply(final Message requestMsg, final byte[] replyContent, final SendCallback replyCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ this.defaultMQPullConsumerImpl.reply(requestMsg, replyContent, replyCallback, timeoutMillis);
+ }
+
+ /**
+ * send a reply message to the producer of the original request message oneway
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ this.defaultMQPullConsumerImpl.replyOneway(requestMsg, replyContent);
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
index 339f799f9a..8aa12a49a2 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumer.java
@@ -30,12 +30,15 @@ import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.consumer.DefaultMQPushConsumerImpl;
import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.trace.AsyncTraceDispatcher;
import org.apache.rocketmq.client.trace.TraceDispatcher;
import org.apache.rocketmq.client.trace.hook.ConsumeMessageTraceHookImpl;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
+import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
@@ -889,4 +892,50 @@ public class DefaultMQPushConsumer extends ClientConfig implements MQPushConsume
public TraceDispatcher getTraceDispatcher() {
return traceDispatcher;
}
+
+ /**
+ * send a reply message to the producer of the original request message
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @param timeoutMillis
+ * @return {@link SendResult} instance to inform senders details of the deliverable, say Message ID of the message,
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ return this.defaultMQPushConsumerImpl.reply(requestMsg, replyContent, timeoutMillis);
+ }
+
+ /**
+ * send a reply message to the producer of the original request message asynchronously
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @param replyCallback callback to execute on replying completion.
+ * @param timeoutMillis
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public void reply(final Message requestMsg, final byte[] replyContent, final SendCallback replyCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ this.defaultMQPushConsumerImpl.reply(requestMsg, replyContent, replyCallback, timeoutMillis);
+ }
+
+ /**
+ * send a reply message to the producer of the original request message oneway
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ this.defaultMQPushConsumerImpl.replyOneway(requestMsg, replyContent);
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
index e9072df3a6..3bea2d8e5d 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/ClientRemotingProcessor.java
@@ -268,13 +268,14 @@ public class ClientRemotingProcessor implements NettyRequestProcessor {
log.debug("receive reply message :{}", msg);
processReplyMessage(msg);
+
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
} catch (Exception e) {
- log.warn("unknown err when receiveRRReplyMsg", e);
+ log.warn("unknown err when receiveReplyMsg", e);
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("process reply message fail");
}
- response.setCode(ResponseCode.SUCCESS);
- response.setRemark(null);
return response;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java
index 598dc94cc2..9975cb835e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java
@@ -43,6 +43,9 @@ import org.apache.rocketmq.client.impl.CommunicationMode;
import org.apache.rocketmq.client.impl.MQClientManager;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.utils.MessageUtil;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ServiceState;
import org.apache.rocketmq.common.UtilAll;
@@ -796,4 +799,25 @@ public class DefaultMQPullConsumerImpl implements MQConsumerInner {
public RebalanceImpl getRebalanceImpl() {
return rebalanceImpl;
}
+
+ @Override
+ public SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ return this.mQClientFactory.getDefaultMQProducer().send(replyMessage, timeoutMillis);
+ }
+
+ @Override
+ public void reply(final Message requestMsg, final byte[] replyContent, final SendCallback sendCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ this.mQClientFactory.getDefaultMQProducer().send(replyMessage, sendCallback, timeoutMillis);
+ }
+
+ @Override
+ public void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws RemotingException, MQClientException, InterruptedException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ this.mQClientFactory.getDefaultMQProducer().sendOneway(replyMessage);
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
index 48fe41ada6..8615746ee2 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
@@ -27,7 +27,6 @@ import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.rocketmq.client.QueryResult;
import org.apache.rocketmq.client.Validators;
@@ -51,20 +50,22 @@ import org.apache.rocketmq.client.impl.CommunicationMode;
import org.apache.rocketmq.client.impl.MQClientManager;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.client.stat.ConsumerStatsManager;
+import org.apache.rocketmq.client.utils.MessageUtil;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ServiceState;
import org.apache.rocketmq.common.UtilAll;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.filter.FilterAPI;
import org.apache.rocketmq.common.help.FAQUrl;
-import org.apache.rocketmq.common.protocol.NamespaceUtil;
-import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
+import org.apache.rocketmq.common.protocol.NamespaceUtil;
import org.apache.rocketmq.common.protocol.body.ConsumeStatus;
import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.common.protocol.body.ProcessQueueInfo;
@@ -75,6 +76,7 @@ import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
import org.apache.rocketmq.common.protocol.route.BrokerData;
import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.common.sysflag.PullSysFlag;
+import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.RPCHook;
import org.apache.rocketmq.remoting.common.RemotingHelper;
import org.apache.rocketmq.remoting.exception.RemotingException;
@@ -1168,4 +1170,25 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
this.consumeMessageService = consumeMessageService;
}
+
+ @Override
+ public SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ return this.mQClientFactory.getDefaultMQProducer().send(replyMessage, timeoutMillis);
+ }
+
+ @Override
+ public void reply(final Message requestMsg, final byte[] replyContent, final SendCallback sendCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ this.mQClientFactory.getDefaultMQProducer().send(replyMessage, sendCallback, timeoutMillis);
+ }
+
+ @Override
+ public void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws RemotingException, MQClientException, InterruptedException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ this.mQClientFactory.getDefaultMQProducer().sendOneway(replyMessage);
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/MQConsumerInner.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/MQConsumerInner.java
index c2e8a1dfc4..010d1db345 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/MQConsumerInner.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/MQConsumerInner.java
@@ -17,12 +17,18 @@
package org.apache.rocketmq.client.impl.consumer;
import java.util.Set;
+import org.apache.rocketmq.client.exception.MQBrokerException;
+import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
+import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.body.ConsumerRunningInfo;
import org.apache.rocketmq.common.protocol.heartbeat.ConsumeType;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.common.protocol.heartbeat.SubscriptionData;
+import org.apache.rocketmq.remoting.exception.RemotingException;
/**
* Consumer inner interface
@@ -49,4 +55,13 @@ public interface MQConsumerInner {
boolean isUnitMode();
ConsumerRunningInfo consumerRunningInfo();
+
+ SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException;
+
+ void reply(final Message requestMsg, final byte[] replyContent, final SendCallback sendCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException;
+
+ void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws RemotingException, MQClientException, InterruptedException;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
index 6e15ed1a09..180ce1974e 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/producer/DefaultMQProducerImpl.java
@@ -1334,6 +1334,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
public Message request(Message msg,
long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, InterruptedException {
+ long beginTimestamp = System.currentTimeMillis();
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1341,6 +1342,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null);
RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+ long cost = System.currentTimeMillis() - beginTimestamp;
this.sendDefaultImpl(msg, CommunicationMode.ASYNC, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
@@ -1353,11 +1355,11 @@ public class DefaultMQProducerImpl implements MQProducerInner {
requestResponseFuture.putResponseMessage(null);
requestResponseFuture.setCause(e);
}
- }, timeout);
+ }, timeout - cost);
- Message responseMessage = requestResponseFuture.waitResponseMessage(timeout);
+ Message responseMessage = requestResponseFuture.waitResponseMessage(timeout - cost);
if (responseMessage == null) {
- if (requestResponseFuture.isSendReqeustOk()) {
+ if (requestResponseFuture.isSendRequestOk()) {
throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
"send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
} else {
@@ -1371,6 +1373,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
public void request(Message msg, final RequestCallback requestCallback, long timeout) throws RemotingException {
+ long beginTimestamp = System.currentTimeMillis();
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1378,6 +1381,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback);
RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+ long cost = System.currentTimeMillis() - beginTimestamp;
this.sendDefaultImpl(msg, CommunicationMode.ASYNC, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
@@ -1389,7 +1393,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
requestResponseFuture.setCause(e);
requestFail(requestUniqId);
}
- }, timeout);
+ }, timeout - cost);
} catch (Exception ex) {
log.warn("send request message to <{}> failed.", msg.getTopic(), ex);
throw new RemotingSendRequestException(msg.getTopic(), ex);
@@ -1399,6 +1403,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
public Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
final long timeout) throws MQClientException, RemotingException, MQBrokerException,
InterruptedException, RequestTimeoutException {
+ long beginTimestamp = System.currentTimeMillis();
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1406,6 +1411,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null);
RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+ long cost = System.currentTimeMillis() - beginTimestamp;
this.sendSelectImpl(msg, selector, arg, CommunicationMode.ASYNC, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
@@ -1418,11 +1424,11 @@ public class DefaultMQProducerImpl implements MQProducerInner {
requestResponseFuture.putResponseMessage(null);
requestResponseFuture.setCause(e);
}
- }, timeout);
+ }, timeout - cost);
- Message responseMessage = requestResponseFuture.waitResponseMessage(timeout);
+ Message responseMessage = requestResponseFuture.waitResponseMessage(timeout - cost);
if (responseMessage == null) {
- if (requestResponseFuture.isSendReqeustOk()) {
+ if (requestResponseFuture.isSendRequestOk()) {
throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
"send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
} else {
@@ -1437,6 +1443,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
public void request(final Message msg, final MessageQueueSelector selector, final Object arg,
final RequestCallback requestCallback, final long timeout) throws RemotingException {
+ long beginTimestamp = System.currentTimeMillis();
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1444,6 +1451,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback);
RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+ long cost = System.currentTimeMillis() - beginTimestamp;
this.sendSelectImpl(msg, selector, arg, CommunicationMode.ASYNC, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
@@ -1455,7 +1463,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
requestResponseFuture.setCause(e);
requestFail(requestUniqId);
}
- }, timeout);
+ }, timeout - cost);
} catch (Exception ex) {
log.warn("send request message to <{}> failed.", msg.getTopic(), ex);
throw new RemotingSendRequestException(msg.getTopic(), ex);
@@ -1464,6 +1472,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
public Message request(final Message msg, final MessageQueue mq, final long timeout)
throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
+ long beginTimestamp = System.currentTimeMillis();
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1471,6 +1480,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null);
RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+ long cost = System.currentTimeMillis() - beginTimestamp;
this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
@@ -1483,11 +1493,11 @@ public class DefaultMQProducerImpl implements MQProducerInner {
requestResponseFuture.putResponseMessage(null);
requestResponseFuture.setCause(e);
}
- }, null, timeout);
+ }, null, timeout - cost);
- Message responseMessage = requestResponseFuture.waitResponseMessage(timeout);
+ Message responseMessage = requestResponseFuture.waitResponseMessage(timeout - cost);
if (responseMessage == null) {
- if (requestResponseFuture.isSendReqeustOk()) {
+ if (requestResponseFuture.isSendRequestOk()) {
throw new RequestTimeoutException(ClientErrorCode.REQUEST_TIMEOUT_EXCEPTION,
"send request message to <" + msg.getTopic() + "> OK, but wait reply message timeout, " + timeout + " ms.");
} else {
@@ -1502,6 +1512,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
throws RemotingException {
+ long beginTimestamp = System.currentTimeMillis();
prepareSendRequest(msg, timeout);
final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID);
@@ -1509,6 +1520,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback);
RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture);
+ long cost = System.currentTimeMillis() - beginTimestamp;
this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, new SendCallback() {
@Override
public void onSuccess(SendResult sendResult) {
@@ -1520,7 +1532,7 @@ public class DefaultMQProducerImpl implements MQProducerInner {
requestResponseFuture.setCause(e);
requestFail(requestUniqId);
}
- }, null, timeout);
+ }, null, timeout - cost);
} catch (Exception ex) {
log.warn("send request message to <{}> failed.", msg.getTopic(), ex);
throw new RemotingSendRequestException(msg.getTopic(), ex);
@@ -1559,20 +1571,6 @@ public class DefaultMQProducerImpl implements MQProducerInner {
}
}
- private SendResult reply(final Message msg,
- long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
- return this.sendDefaultImpl(msg, CommunicationMode.SYNC, null, timeoutMillis);
- }
-
- private SendResult reply(final Message msg, final SendCallback sendCallback,
- long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
- return this.sendDefaultImpl(msg, CommunicationMode.ASYNC, sendCallback, timeoutMillis);
- }
-
- public void replyOneway(final Message msg) throws RemotingException, MQClientException, InterruptedException {
- this.sendOneway(msg);
- }
-
public ConcurrentMap getTopicPublishInfoTable() {
return topicPublishInfoTable;
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
index bb017ef212..fdb489eebd 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/DefaultMQProducer.java
@@ -566,13 +566,19 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
}
/**
- * @param msg
- * @param timeout
- * @return
- * @throws MQClientException
- * @throws RemotingException
- * @throws MQBrokerException
- * @throws InterruptedException
+ * Send request message in synchronous mode. This method returns only when the consumer consume the request message and reply a message.
+ *
+ * Warn: this method has internal retry-mechanism, that is, internal implementation will retry
+ * {@link #retryTimesWhenSendFailed} times before claiming failure. As a result, multiple messages may potentially
+ * delivered to broker(s). It's up to the application developers to resolve potential duplication issue.
+ *
+ * @param msg request message to send
+ * @param timeout request timeout
+ * @return reply message
+ * @throws MQClientException if there is any client error.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQBrokerException if there is any broker error.
+ * @throws InterruptedException if the thread is interrupted.
*/
@Override
public Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException,
@@ -582,85 +588,101 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer {
}
/**
- * @param msg
- * @param requestCallback
- * @param timeout
- * @return
- * @throws MQClientException
- * @throws RemotingException
- * @throws InterruptedException
+ * Request asynchronously.
+ * This method returns immediately. On receiving reply message, requestCallback will be executed.
+ *
+ * Similar to {@link #request(Message, long)}, internal implementation would potentially retry up to {@link
+ * #retryTimesWhenSendAsyncFailed} times before claiming sending failure, which may yield message duplication and
+ * application developers are the one to resolve this potential issue.
+ *
+ * @param msg request message to send
+ * @param requestCallback callback to execute on request completion.
+ * @param timeout request timeout
+ * @throws MQClientException if there is any client error.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws InterruptedException if the thread is interrupted.
*/
@Override
public void request(final Message msg, final RequestCallback requestCallback, final long timeout)
throws MQClientException, RemotingException, InterruptedException, MQBrokerException, RequestTimeoutException {
+ msg.setTopic(withNamespace(msg.getTopic()));
this.defaultMQProducerImpl.request(msg, requestCallback, timeout);
}
/**
- * @param msg
- * @param selector
- * @param arg
- * @param timeout
- * @return
- * @throws MQClientException
- * @throws RemotingException
- * @throws MQBrokerException
- * @throws InterruptedException
+ * Same to {@link #request(Message, long)} with message queue selector specified.
+ *
+ * @param msg request message to send
+ * @param selector message queue selector, through which we get target message queue to deliver message to.
+ * @param arg argument to work along with message queue selector.
+ * @param timeout timeout of request.
+ * @return reply message
+ * @throws MQClientException if there is any client error.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQBrokerException if there is any broker error.
+ * @throws InterruptedException if the thread is interrupted.
*/
@Override
public Message request(final Message msg, final MessageQueueSelector selector, final Object arg,
final long timeout) throws MQClientException, RemotingException, MQBrokerException,
InterruptedException, RequestTimeoutException {
+ msg.setTopic(withNamespace(msg.getTopic()));
return this.defaultMQProducerImpl.request(msg, selector, arg, timeout);
}
/**
- * @param msg
- * @param selector
- * @param arg
- * @param requestCallback
- * @param timeout
- * @return
- * @throws MQClientException
- * @throws RemotingException
- * @throws InterruptedException
+ * Same to {@link #request(Message, RequestCallback, long)} with target message selector specified.
+ *
+ * @param msg requst message to send
+ * @param selector message queue selector, through which we get target message queue to deliver message to.
+ * @param arg argument to work along with message queue selector.
+ * @param requestCallback callback to execute on request completion.
+ * @param timeout timeout of request.
+ * @throws MQClientException if there is any client error.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws InterruptedException if the thread is interrupted.
*/
@Override
public void request(final Message msg, final MessageQueueSelector selector, final Object arg,
final RequestCallback requestCallback, final long timeout) throws MQClientException, RemotingException,
InterruptedException {
+ msg.setTopic(withNamespace(msg.getTopic()));
this.defaultMQProducerImpl.request(msg, selector, arg, requestCallback, timeout);
}
/**
- * @param msg
- * @param mq
- * @param timeout
- * @return
- * @throws MQClientException
- * @throws RemotingException
- * @throws MQBrokerException
- * @throws InterruptedException
+ * Same to {@link #request(Message, long)} with target message queue specified in addition.
+ *
+ * @param msg request message to send
+ * @param mq target message queue.
+ * @param timeout request timeout
+ * @throws MQClientException if there is any client error.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQBrokerException if there is any broker error.
+ * @throws InterruptedException if the thread is interrupted.
*/
@Override
public Message request(final Message msg, final MessageQueue mq, final long timeout)
throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException {
+ msg.setTopic(withNamespace(msg.getTopic()));
return this.defaultMQProducerImpl.request(msg, mq, timeout);
}
/**
- * @param msg
- * @param mq
- * @param requestCallback
- * @param timeout
- * @return
- * @throws MQClientException
- * @throws RemotingException
- * @throws InterruptedException
+ * Same to {@link #request(Message, RequestCallback, long)} with target message queue specified.
+ *
+ * @param msg request message to send
+ * @param mq target message queue.
+ * @param requestCallback callback to execute on request completion.
+ * @param timeout timeout of request.
+ * @throws MQClientException if there is any client error.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws InterruptedException if the thread is interrupted.
*/
@Override
public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout)
throws MQClientException, RemotingException, InterruptedException {
+ msg.setTopic(withNamespace(msg.getTopic()));
this.defaultMQProducerImpl.request(msg, mq, requestCallback, timeout);
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java b/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
index d65b479434..c476ba30f1 100644
--- a/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
+++ b/client/src/main/java/org/apache/rocketmq/client/producer/RequestResponseFuture.java
@@ -19,7 +19,6 @@ package org.apache.rocketmq.client.producer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.rocketmq.common.message.Message;
public class RequestResponseFuture {
@@ -29,9 +28,8 @@ public class RequestResponseFuture {
private final Message requestMsg = null;
private long timeoutMillis;
private CountDownLatch countDownLatch = new CountDownLatch(1);
- private AtomicBoolean ececuteCallbackOnlyOnce = new AtomicBoolean(false);
private volatile Message responseMsg = null;
- private volatile boolean sendReqeustOk = true;
+ private volatile boolean sendRequestOk = true;
private volatile Throwable cause = null;
public RequestResponseFuture(String requestUniqId, long timeoutMillis, RequestCallback requestCallback) {
@@ -42,7 +40,7 @@ public class RequestResponseFuture {
public void executeRequestCallback() {
if (requestCallback != null) {
- if (sendReqeustOk && cause == null) {
+ if (sendRequestOk && cause == null) {
requestCallback.onSuccess(responseMsg);
} else {
requestCallback.onException(cause);
@@ -93,14 +91,6 @@ public class RequestResponseFuture {
this.countDownLatch = countDownLatch;
}
- public AtomicBoolean getEcecuteCallbackOnlyOnce() {
- return ececuteCallbackOnlyOnce;
- }
-
- public void setEcecuteCallbackOnlyOnce(AtomicBoolean ececuteCallbackOnlyOnce) {
- this.ececuteCallbackOnlyOnce = ececuteCallbackOnlyOnce;
- }
-
public Message getResponseMsg() {
return responseMsg;
}
@@ -109,12 +99,12 @@ public class RequestResponseFuture {
this.responseMsg = responseMsg;
}
- public boolean isSendReqeustOk() {
- return sendReqeustOk;
+ public boolean isSendRequestOk() {
+ return sendRequestOk;
}
public void setSendReqeustOk(boolean sendReqeustOk) {
- this.sendReqeustOk = sendReqeustOk;
+ this.sendRequestOk = sendReqeustOk;
}
public Message getRequestMsg() {
diff --git a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
index e60c0f665f..1e975a9a98 100644
--- a/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
+++ b/client/src/main/java/org/apache/rocketmq/client/utils/MessageUtil.java
@@ -41,8 +41,10 @@ public class MessageUtil {
MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TTL, ttl);
return replyMessage;
+ } else {
+ throw new MQClientException(-1, "create reply message fail, requestMessage error, property[" + MessageConst.PROPERTY_CLUSTER + "] is null.");
}
}
- throw new MQClientException(-1, "create reply message fail.");
+ throw new MQClientException(-1, "create reply message fail, requestMessage cannot be null.");
}
}
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
index b038151a88..b34908b84f 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/RequestProducer.java
@@ -18,15 +18,11 @@
package org.apache.rocketmq.example.rpc;
import org.apache.rocketmq.client.exception.MQClientException;
-import org.apache.rocketmq.client.log.ClientLogger;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
-import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.common.RemotingHelper;
public class RequestProducer {
- private static final InternalLogger log = ClientLogger.getLog();
-
public static void main(String[] args) throws MQClientException, InterruptedException {
String producerGroup = "please_rename_unique_group_name";
String topic = "RequestTopic";
@@ -43,9 +39,9 @@ public class RequestProducer {
long begin = System.currentTimeMillis();
Message retMsg = producer.request(msg, ttl);
long cost = System.currentTimeMillis() - begin;
- System.err.printf("request to <%s> cost: %d replyMessage: %s %n", topic, cost, retMsg);
+ System.out.printf("request to <%s> cost: %d replyMessage: %s %n", topic, cost, retMsg);
} catch (Exception e) {
- log.warn("", e);
+ e.printStackTrace();
}
producer.shutdown();
}
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
index 131fc9dfcc..a130722a71 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
@@ -24,19 +24,13 @@ import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
-import org.apache.rocketmq.client.log.ClientLogger;
import org.apache.rocketmq.client.producer.SendResult;
-import org.apache.rocketmq.client.utils.MessageUtil;
import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
-import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageExt;
-import org.apache.rocketmq.logging.InternalLogger;
import org.apache.rocketmq.remoting.exception.RemotingException;
public class ResponseConsumer {
- private static final InternalLogger log = ClientLogger.getLog();
-
public static void main(String[] args) throws InterruptedException, MQClientException {
String consumerGroup = "please_rename_unique_group_name";
String topic = "RequestTopic";
@@ -50,23 +44,13 @@ public class ResponseConsumer {
System.out.printf("%s Receive New Messages: %s %n", Thread.currentThread().getName(), msgs);
for (MessageExt msg : msgs) {
try {
- log.info("handle message: {} body={}", msg, new String(msg.getBody()));
+ System.out.printf("handle message: %s", msg.toString());
String replyTo = msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
- //You must use MessageUtil to creage reply message, otherwise reply message maybe wrong.
byte[] replyContent = "reply message contents.".getBytes();
- Message replyMessage = MessageUtil.createReplyMessage(msg, replyContent);
-
- //maybe you should create a producer to send reply message.
- SendResult sendResult = consumer.getDefaultMQPushConsumerImpl().getmQClientFactory().getDefaultMQProducer().send(replyMessage, 3000);
- System.out.printf("reply msg %s to %s , %s %n", replyMessage.toString(), replyTo, sendResult.toString());
- } catch (MQClientException e) {
- e.printStackTrace();
- } catch (RemotingException e) {
- e.printStackTrace();
- } catch (MQBrokerException e) {
- e.printStackTrace();
- } catch (InterruptedException e) {
+ SendResult replyResult = consumer.reply(msg, replyContent, 3000);
+ System.out.printf("reply to %s , %s %n", replyTo, replyResult.toString());
+ } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) {
e.printStackTrace();
}
}
From 8c372b4596d64f90e41e38534820baf655b3f1a1 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Mon, 23 Sep 2019 21:30:56 +0800
Subject: [PATCH 11/26] optimize ReplyMessageProcessor
---
.../processor/ReplyMessageProcessor.java | 146 ++++++++++--------
1 file changed, 85 insertions(+), 61 deletions(-)
diff --git a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
index 23e1e9ac8b..265c5c122f 100644
--- a/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
+++ b/broker/src/main/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessor.java
@@ -23,6 +23,7 @@ import org.apache.rocketmq.broker.BrokerController;
import org.apache.rocketmq.broker.mqtrace.SendMessageContext;
import org.apache.rocketmq.common.TopicConfig;
import org.apache.rocketmq.common.UtilAll;
+import org.apache.rocketmq.common.constant.LoggerName;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageConst;
@@ -34,6 +35,8 @@ import org.apache.rocketmq.common.protocol.header.ReplyMessageRequestHeader;
import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeaderV2;
import org.apache.rocketmq.common.protocol.header.SendMessageResponseHeader;
+import org.apache.rocketmq.logging.InternalLogger;
+import org.apache.rocketmq.logging.InternalLoggerFactory;
import org.apache.rocketmq.remoting.exception.RemotingCommandException;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.apache.rocketmq.remoting.netty.NettyRequestProcessor;
@@ -43,6 +46,7 @@ import org.apache.rocketmq.store.PutMessageResult;
import org.apache.rocketmq.store.stats.BrokerStatsManager;
public class ReplyMessageProcessor extends AbstractSendMessageProcessor implements NettyRequestProcessor {
+ private static final InternalLogger log = InternalLoggerFactory.getLogger(LoggerName.BROKER_LOGGER_NAME);
public ReplyMessageProcessor(final BrokerController brokerController) {
super(brokerController);
@@ -136,22 +140,20 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
msgInner.setStoreHost(this.getStoreHost());
msgInner.setReconsumeTimes(requestHeader.getReconsumeTimes() == null ? 0 : requestHeader.getReconsumeTimes());
- boolean pushOk = this.pushReplyMessage(ctx, requestHeader, msgInner, response);
+ PushReplyResult pushReplyResult = this.pushReplyMessage(ctx, requestHeader, msgInner);
+ this.handlePushReplyResult(pushReplyResult, response, responseHeader, queueIdInt);
- if (pushOk && this.brokerController.getBrokerConfig().isStoreReplyMessageEnable()) {
+ if (this.brokerController.getBrokerConfig().isStoreReplyMessageEnable()) {
PutMessageResult putMessageResult = this.brokerController.getMessageStore().putMessage(msgInner);
- this.handlePutMessageResult(putMessageResult, response, request, msgInner, responseHeader, sendMessageContext, ctx, queueIdInt);
- } else {
- responseHeader.setMsgId("0");
- responseHeader.setQueueId(0);
- responseHeader.setQueueOffset(0L);
+ this.handlePutMessageResult(putMessageResult, request, msgInner, responseHeader, sendMessageContext, queueIdInt);
}
return response;
}
- private boolean pushReplyMessage(final ChannelHandlerContext ctx, final SendMessageRequestHeader requestHeader,
- final Message msg, final RemotingCommand response) {
+ private PushReplyResult pushReplyMessage(final ChannelHandlerContext ctx,
+ final SendMessageRequestHeader requestHeader,
+ final Message msg) {
ReplyMessageRequestHeader replyMessageRequestHeader = new ReplyMessageRequestHeader();
replyMessageRequestHeader.setBornHost(ctx.channel().remoteAddress().toString());
replyMessageRequestHeader.setStoreHost(this.getStoreHost().toString());
@@ -172,7 +174,7 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
request.setBody(msg.getBody());
String senderId = msg.getProperties().get(MessageConst.PROPERTY_MESSAGE_REPLY_TO);
- boolean pushOk = false;
+ PushReplyResult pushReplyResult = new PushReplyResult(false);
if (senderId != null) {
Channel channel = this.brokerController.getProducerManager().findChannel(senderId);
@@ -185,106 +187,102 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
assert pushResponse != null;
switch (pushResponse.getCode()) {
case ResponseCode.SUCCESS: {
- response.setCode(ResponseCode.SUCCESS);
- response.setRemark(null);
- pushOk = true;
+ pushReplyResult.setPushOk(true);
break;
}
default: {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("push reply message to requester fail");
- log.warn("push reply message to <{}> return fail, remark: {}", senderId, response.getRemark());
+ pushReplyResult.setPushOk(false);
+ pushReplyResult.setRemark("push reply message to " + senderId + "fail.");
+ log.warn("push reply message to <{}> return fail, response remark: {}", senderId, pushResponse.getRemark());
}
}
- } catch (InterruptedException e) {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("push reply message to requester fail");
- log.warn("push reply message to <{}> fail. {}", senderId, channel, e);
- } catch (RemotingException e) {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("push reply message to requester fail");
+ } catch (RemotingException | InterruptedException e) {
+ pushReplyResult.setPushOk(false);
+ pushReplyResult.setRemark("push reply message to " + senderId + "fail.");
log.warn("push reply message to <{}> fail. {}", senderId, channel, e);
}
} else {
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("channel of <" + senderId + "> not found");
- log.warn("push reply message fial, channel of <{}> not found.", senderId);
+ pushReplyResult.setPushOk(false);
+ pushReplyResult.setRemark("push reply message fail, channel of <" + senderId + "> not found.");
+ log.warn(pushReplyResult.getRemark());
}
- return pushOk;
+ } else {
+ log.warn("REPLY_TO is null, can not reply message");
+ pushReplyResult.setPushOk(false);
+ pushReplyResult.setRemark("reply message properties[" + MessageConst.PROPERTY_MESSAGE_REPLY_TO + "] is null");
}
- log.warn("REPLY_TO is null, can not reply message");
- response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("REPLY_TO is null");
- return pushOk;
+ return pushReplyResult;
}
- private void handlePutMessageResult(PutMessageResult putMessageResult, final RemotingCommand response,
+ private void handlePushReplyResult(PushReplyResult pushReplyResult, final RemotingCommand response,
+ final SendMessageResponseHeader responseHeader, int queueIdInt) {
+
+ if (!pushReplyResult.isPushOk()) {
+ response.setCode(ResponseCode.SYSTEM_ERROR);
+ response.setRemark(pushReplyResult.getRemark());
+ } else {
+ response.setCode(ResponseCode.SUCCESS);
+ response.setRemark(null);
+ //set to zore to avoid client decoding exception
+ responseHeader.setMsgId("0");
+ responseHeader.setQueueId(queueIdInt);
+ responseHeader.setQueueOffset(0L);
+ }
+ }
+
+ private void handlePutMessageResult(PutMessageResult putMessageResult,
final RemotingCommand request, final MessageExt msg,
final SendMessageResponseHeader responseHeader, SendMessageContext sendMessageContext,
- ChannelHandlerContext ctx,
int queueIdInt) {
if (putMessageResult == null) {
- response.setRemark("push reply to requester success, but store putMessage return null");
+ log.warn("process reply message, store putMessage return null");
return;
}
- boolean sendOK = false;
+ boolean putOk = false;
switch (putMessageResult.getPutMessageStatus()) {
// Success
case PUT_OK:
- sendOK = true;
- response.setCode(ResponseCode.SUCCESS);
- break;
case FLUSH_DISK_TIMEOUT:
- response.setCode(ResponseCode.FLUSH_DISK_TIMEOUT);
- sendOK = true;
- break;
case FLUSH_SLAVE_TIMEOUT:
- response.setCode(ResponseCode.FLUSH_SLAVE_TIMEOUT);
- sendOK = true;
- break;
case SLAVE_NOT_AVAILABLE:
- response.setCode(ResponseCode.SLAVE_NOT_AVAILABLE);
- sendOK = true;
+ putOk = true;
break;
// Failed
case CREATE_MAPEDFILE_FAILED:
-// response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("create mapped file failed, server is busy or broken.");
+ log.info("create mapped file failed, server is busy or broken.");
break;
case MESSAGE_ILLEGAL:
+ log.info(
+ "the message is illegal, maybe msg properties length limit 32k.");
+ break;
case PROPERTIES_SIZE_EXCEEDED:
-// response.setCode(ResponseCode.MESSAGE_ILLEGAL);
- response.setRemark(
- "the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k, msg properties length limit 32k.");
+ log.info(
+ "the message is illegal, maybe msg body or properties length not matched. msg body length limit 128k.");
break;
case SERVICE_NOT_AVAILABLE:
-// response.setCode(ResponseCode.SERVICE_NOT_AVAILABLE);
- response.setRemark(
+ log.info(
"service not available now, maybe disk full, maybe your broker machine memory too small.");
break;
case OS_PAGECACHE_BUSY:
-// response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("[PC_SYNCHRONIZED]broker busy, start flow control for a while");
+ log.info("[PC_SYNCHRONIZED]broker busy, start flow control for a while");
break;
case UNKNOWN_ERROR:
-// response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("UNKNOWN_ERROR");
+ log.info("UNKNOWN_ERROR");
break;
default:
-// response.setCode(ResponseCode.SYSTEM_ERROR);
- response.setRemark("UNKNOWN_ERROR DEFAULT");
+ log.info("UNKNOWN_ERROR DEFAULT");
break;
}
String owner = request.getExtFields().get(BrokerStatsManager.COMMERCIAL_OWNER);
- if (sendOK) {
+ if (putOk) {
this.brokerController.getBrokerStatsManager().incTopicPutNums(msg.getTopic(), putMessageResult.getAppendMessageResult().getMsgNum(), 1);
this.brokerController.getBrokerStatsManager().incTopicPutSize(msg.getTopic(),
putMessageResult.getAppendMessageResult().getWroteBytes());
this.brokerController.getBrokerStatsManager().incBrokerPutNums(putMessageResult.getAppendMessageResult().getMsgNum());
- response.setRemark(null);
+
responseHeader.setMsgId(putMessageResult.getAppendMessageResult().getMsgId());
responseHeader.setQueueId(queueIdInt);
responseHeader.setQueueOffset(putMessageResult.getAppendMessageResult().getLogicsOffset());
@@ -315,4 +313,30 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen
}
}
}
+
+ class PushReplyResult {
+ boolean pushOk;
+ String remark;
+
+ public PushReplyResult(boolean pushOk) {
+ this.pushOk = pushOk;
+ remark = "";
+ }
+
+ public boolean isPushOk() {
+ return pushOk;
+ }
+
+ public void setPushOk(boolean pushOk) {
+ this.pushOk = pushOk;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+ }
}
From cc7543ff756c535df0e9d1b395563a2be1e4d1ef Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Tue, 24 Sep 2019 21:28:49 +0800
Subject: [PATCH 12/26] add reply interface to DefaultLitePullConsumer
---
.../consumer/DefaultLitePullConsumer.java | 51 +++++++++++++++++++
.../consumer/DefaultLitePullConsumerImpl.java | 25 +++++++++
.../client/utils/MessageUtilsTest.java | 2 +-
3 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java
index 99976d55d3..460558e407 100644
--- a/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java
+++ b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultLitePullConsumer.java
@@ -22,13 +22,18 @@ import java.util.List;
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.consumer.rebalance.AllocateMessageQueueAveragely;
import org.apache.rocketmq.client.consumer.store.OffsetStore;
+import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.impl.consumer.DefaultLitePullConsumerImpl;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.MixAll;
+import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.heartbeat.MessageModel;
import org.apache.rocketmq.remoting.RPCHook;
+import org.apache.rocketmq.remoting.exception.RemotingException;
public class DefaultLitePullConsumer extends ClientConfig implements LitePullConsumer {
@@ -411,4 +416,50 @@ public class DefaultLitePullConsumer extends ClientConfig implements LitePullCon
public void setTopicMetadataCheckIntervalMillis(long topicMetadataCheckIntervalMillis) {
this.topicMetadataCheckIntervalMillis = topicMetadataCheckIntervalMillis;
}
+
+ /**
+ * send a reply message to the producer of the original request message
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @param timeoutMillis
+ * @return {@link SendResult} instance to inform senders details of the deliverable, say Message ID of the message,
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ return this.defaultLitePullConsumerImpl.reply(requestMsg, replyContent, timeoutMillis);
+ }
+
+ /**
+ * send a reply message to the producer of the original request message asynchronously
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @param replyCallback callback to execute on replying completion.
+ * @param timeoutMillis
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public void reply(final Message requestMsg, final byte[] replyContent, final SendCallback replyCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ this.defaultLitePullConsumerImpl.reply(requestMsg, replyContent, replyCallback, timeoutMillis);
+ }
+
+ /**
+ * send a reply message to the producer of the original request message oneway
+ * @param requestMsg original request message
+ * @param replyContent contents of reply message
+ * @throws InterruptedException if the thread is interrupted.
+ * @throws RemotingException if there is any network-tier error.
+ * @throws MQClientException if there is any client error.
+ * @throws MQBrokerException if there is any broker error.
+ */
+ public void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ this.defaultLitePullConsumerImpl.replyOneway(requestMsg, replyContent);
+ }
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
index a37c3a0149..9308fad7c7 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
@@ -53,6 +53,9 @@ import org.apache.rocketmq.client.impl.CommunicationMode;
import org.apache.rocketmq.client.impl.MQClientManager;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
import org.apache.rocketmq.client.log.ClientLogger;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.utils.MessageUtil;
import org.apache.rocketmq.common.MixAll;
import org.apache.rocketmq.common.ServiceState;
import org.apache.rocketmq.common.ThreadFactoryImpl;
@@ -60,6 +63,7 @@ import org.apache.rocketmq.common.consumer.ConsumeFromWhere;
import org.apache.rocketmq.common.filter.ExpressionType;
import org.apache.rocketmq.common.filter.FilterAPI;
import org.apache.rocketmq.common.help.FAQUrl;
+import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.NamespaceUtil;
@@ -1070,4 +1074,25 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
}
+
+ @Override
+ public SendResult reply(final Message requestMsg, final byte[] replyContent,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ return this.mQClientFactory.getDefaultMQProducer().send(replyMessage, timeoutMillis);
+ }
+
+ @Override
+ public void reply(final Message requestMsg, final byte[] replyContent, final SendCallback sendCallback,
+ long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ this.mQClientFactory.getDefaultMQProducer().send(replyMessage, sendCallback, timeoutMillis);
+ }
+
+ @Override
+ public void replyOneway(final Message requestMsg,
+ final byte[] replyContent) throws RemotingException, MQClientException, InterruptedException {
+ Message replyMessage = MessageUtil.createReplyMessage(requestMsg, replyContent);
+ this.mQClientFactory.getDefaultMQProducer().sendOneway(replyMessage);
+ }
}
diff --git a/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java b/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java
index a722fa6cbb..406979c9f8 100644
--- a/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/utils/MessageUtilsTest.java
@@ -45,7 +45,7 @@ public class MessageUtilsTest {
Message msg = MessageUtil.createReplyMessage(createReplyMessage(null), new byte[] {'a'});
failBecauseExceptionWasNotThrown(MQClientException.class);
} catch (MQClientException e) {
- assertThat(e).hasMessageContaining("create reply message fail.");
+ assertThat(e).hasMessageContaining("create reply message fail, requestMessage error, property[" + MessageConst.PROPERTY_CLUSTER + "] is null.");
}
}
From 777285011e81d145b067a6e73816a6a5c533057f Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Wed, 25 Sep 2019 10:31:31 +0800
Subject: [PATCH 13/26] fix unit test err
---
.../rocketmq/broker/processor/ReplyMessageProcessorTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java b/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
index f48594ebbe..a28f780601 100644
--- a/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
+++ b/broker/src/test/java/org/apache/rocketmq/broker/processor/ReplyMessageProcessorTest.java
@@ -92,7 +92,6 @@ public class ReplyMessageProcessorTest {
Channel mockChannel = mock(Channel.class);
when(mockChannel.remoteAddress()).thenReturn(new InetSocketAddress(1024));
when(handlerContext.channel()).thenReturn(mockChannel);
- when(messageStore.lookMessageByOffset(anyLong())).thenReturn(new MessageExt());
replyMessageProcessor = new ReplyMessageProcessor(brokerController);
}
From 0c47fcf7164f98bdedb9b35284206eb4eb4e9052 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Thu, 26 Sep 2019 21:19:48 +0800
Subject: [PATCH 14/26] add recommend client configs in rpc mode
---
.../apache/rocketmq/client/ClientConfig.java | 16 ++++++++++++++--
.../consumer/DefaultLitePullConsumerImpl.java | 9 +++++++--
.../consumer/DefaultMQPushConsumerImpl.java | 17 +++++++++++------
.../rocketmq/example/rpc/ResponseConsumer.java | 2 ++
4 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
index c3e4efa252..d0ae5e1b83 100644
--- a/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
+++ b/client/src/main/java/org/apache/rocketmq/client/ClientConfig.java
@@ -53,6 +53,7 @@ public class ClientConfig {
* Offset persistent interval for consumer
*/
private int persistConsumerOffsetInterval = 1000 * 5;
+ private long pullTimeDelayMillsWhenException = 1000;
private boolean unitMode = false;
private String unitName;
private boolean vipChannelEnabled = Boolean.parseBoolean(System.getProperty(SEND_MESSAGE_WITH_VIP_CHANNEL_PROPERTY, "false"));
@@ -148,6 +149,7 @@ public class ClientConfig {
this.pollNameServerInterval = cc.pollNameServerInterval;
this.heartbeatBrokerInterval = cc.heartbeatBrokerInterval;
this.persistConsumerOffsetInterval = cc.persistConsumerOffsetInterval;
+ this.pullTimeDelayMillsWhenException = cc.pullTimeDelayMillsWhenException;
this.unitMode = cc.unitMode;
this.unitName = cc.unitName;
this.vipChannelEnabled = cc.vipChannelEnabled;
@@ -165,6 +167,7 @@ public class ClientConfig {
cc.pollNameServerInterval = pollNameServerInterval;
cc.heartbeatBrokerInterval = heartbeatBrokerInterval;
cc.persistConsumerOffsetInterval = persistConsumerOffsetInterval;
+ cc.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;
cc.unitMode = unitMode;
cc.unitName = unitName;
cc.vipChannelEnabled = vipChannelEnabled;
@@ -222,6 +225,14 @@ public class ClientConfig {
this.persistConsumerOffsetInterval = persistConsumerOffsetInterval;
}
+ public long getPullTimeDelayMillsWhenException() {
+ return pullTimeDelayMillsWhenException;
+ }
+
+ public void setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) {
+ this.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;
+ }
+
public String getUnitName() {
return unitName;
}
@@ -287,12 +298,13 @@ public class ClientConfig {
this.accessChannel = accessChannel;
}
+
@Override
public String toString() {
return "ClientConfig [namesrvAddr=" + namesrvAddr + ", clientIP=" + clientIP + ", instanceName=" + instanceName
+ ", clientCallbackExecutorThreads=" + clientCallbackExecutorThreads + ", pollNameServerInterval=" + pollNameServerInterval
- + ", heartbeatBrokerInterval=" + heartbeatBrokerInterval + ", persistConsumerOffsetInterval="
- + persistConsumerOffsetInterval + ", unitMode=" + unitMode + ", unitName=" + unitName + ", vipChannelEnabled="
+ + ", heartbeatBrokerInterval=" + heartbeatBrokerInterval + ", persistConsumerOffsetInterval=" + persistConsumerOffsetInterval
+ + ", pullTimeDelayMillsWhenException=" + pullTimeDelayMillsWhenException + ", unitMode=" + unitMode + ", unitName=" + unitName + ", vipChannelEnabled="
+ vipChannelEnabled + ", useTLS=" + useTLS + ", language=" + language.name() + ", namespace=" + namespace + "]";
}
}
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
index 9308fad7c7..d094f661f7 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java
@@ -110,7 +110,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
/**
* Delay some time when exception occur
*/
- private static final long PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION = 1000;
+ private long pullTimeDelayMillsWhenException = 1000;
/**
* Flow control interval
*/
@@ -160,6 +160,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
return new Thread(r, "MonitorMessageQueueChangeThread");
}
});
+ this.pullTimeDelayMillsWhenException = defaultLitePullConsumer.getPullTimeDelayMillsWhenException();
}
private void checkServiceState() {
@@ -787,7 +788,7 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
updatePullOffset(messageQueue, pullResult.getNextBeginOffset());
} catch (Throwable e) {
- pullDelayTimeMills = PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION;
+ pullDelayTimeMills = pullTimeDelayMillsWhenException;
log.error("An error occurred in pull message process.", e);
}
@@ -1075,6 +1076,10 @@ public class DefaultLitePullConsumerImpl implements MQConsumerInner {
}
+ public void setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) {
+ this.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;
+ }
+
@Override
public SendResult reply(final Message requestMsg, final byte[] replyContent,
long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
diff --git a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
index ac92dc9ff5..20c59609ed 100644
--- a/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
+++ b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPushConsumerImpl.java
@@ -85,7 +85,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
/**
* Delay some time when exception occur
*/
- private static final long PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION = 3000;
+ private long pullTimeDelayMillsWhenException = 3000;
/**
* Flow control interval
*/
@@ -117,6 +117,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
public DefaultMQPushConsumerImpl(DefaultMQPushConsumer defaultMQPushConsumer, RPCHook rpcHook) {
this.defaultMQPushConsumer = defaultMQPushConsumer;
this.rpcHook = rpcHook;
+ this.pullTimeDelayMillsWhenException = defaultMQPushConsumer.getPullTimeDelayMillsWhenException();
}
public void registerFilterMessageHook(final FilterMessageHook hook) {
@@ -224,7 +225,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
this.makeSureStateOK();
} catch (MQClientException e) {
log.warn("pullMessage exception, consumer state not ok", e);
- this.executePullRequestLater(pullRequest, PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION);
+ this.executePullRequestLater(pullRequest, pullTimeDelayMillsWhenException);
return;
}
@@ -284,7 +285,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
pullRequest.setNextOffset(offset);
}
} else {
- this.executePullRequestLater(pullRequest, PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION);
+ this.executePullRequestLater(pullRequest, pullTimeDelayMillsWhenException);
log.info("pull message later because not locked in broker, {}", pullRequest);
return;
}
@@ -292,7 +293,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
final SubscriptionData subscriptionData = this.rebalanceImpl.getSubscriptionInner().get(pullRequest.getMessageQueue().getTopic());
if (null == subscriptionData) {
- this.executePullRequestLater(pullRequest, PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION);
+ this.executePullRequestLater(pullRequest, pullTimeDelayMillsWhenException);
log.warn("find the consumer's subscription failed, {}", pullRequest);
return;
}
@@ -399,7 +400,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
log.warn("execute the pull request exception", e);
}
- DefaultMQPushConsumerImpl.this.executePullRequestLater(pullRequest, PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION);
+ DefaultMQPushConsumerImpl.this.executePullRequestLater(pullRequest, pullTimeDelayMillsWhenException);
}
};
@@ -446,7 +447,7 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
);
} catch (Exception e) {
log.error("pullKernelImpl exception", e);
- this.executePullRequestLater(pullRequest, PULL_TIME_DELAY_MILLS_WHEN_EXCEPTION);
+ this.executePullRequestLater(pullRequest, pullTimeDelayMillsWhenException);
}
}
@@ -1171,6 +1172,10 @@ public class DefaultMQPushConsumerImpl implements MQConsumerInner {
}
+ public void setPullTimeDelayMillsWhenException(long pullTimeDelayMillsWhenException) {
+ this.pullTimeDelayMillsWhenException = pullTimeDelayMillsWhenException;
+ }
+
@Override
public SendResult reply(final Message requestMsg, final byte[] replyContent,
long timeoutMillis) throws InterruptedException, RemotingException, MQClientException, MQBrokerException {
diff --git a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
index a130722a71..f3b3fd1156 100644
--- a/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
+++ b/example/src/main/java/org/apache/rocketmq/example/rpc/ResponseConsumer.java
@@ -37,6 +37,8 @@ public class ResponseConsumer {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup);
consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET);
+ //recommend client configs
+ consumer.setPullTimeDelayMillsWhenException(0L);
consumer.registerMessageListener(new MessageListenerConcurrently() {
@Override
From e7b9169b3098c00ac66610d1522910e0ebf2b595 Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Sun, 29 Sep 2019 15:10:25 +0800
Subject: [PATCH 15/26] optimize unit test
---
.../producer/DefaultMQProducerTest.java | 25 ++++++++++---------
1 file changed, 13 insertions(+), 12 deletions(-)
diff --git a/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java b/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java
index 941ee73f42..991a572529 100644
--- a/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/producer/DefaultMQProducerTest.java
@@ -27,8 +27,8 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-
import org.apache.rocketmq.client.ClientConfig;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
@@ -319,24 +319,25 @@ public class DefaultMQProducerTest {
@Test
public void testRequestMessage() throws RemotingException, RequestTimeoutException, MQClientException, InterruptedException, MQBrokerException {
when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
+ final AtomicBoolean finish = new AtomicBoolean(false);
new Thread(new Runnable() {
@Override public void run() {
- boolean flag = true;
- ConcurrentHashMap responseMap = null;
- while (flag) {
- responseMap = RequestFutureTable.getRequestFutureTable();
- if (responseMap != null) {
- flag = false;
- }
- }
+ ConcurrentHashMap responseMap = RequestFutureTable.getRequestFutureTable();
assertThat(responseMap).isNotNull();
- for (Map.Entry entry : responseMap.entrySet()) {
- RequestResponseFuture future = entry.getValue();
- future.putResponseMessage(message);
+ while (!finish.get()) {
+ try {
+ Thread.sleep(10);
+ } catch (InterruptedException e) {
+ }
+ for (Map.Entry entry : responseMap.entrySet()) {
+ RequestResponseFuture future = entry.getValue();
+ future.putResponseMessage(message);
+ }
}
}
}).start();
Message result = producer.request(message, 3 * 1000L);
+ finish.getAndSet(true);
assertThat(result.getTopic()).isEqualTo("FooBar");
assertThat(result.getBody()).isEqualTo(new byte[] {'a'});
}
From 8353551d0cb1fdffab67deb89362d9b70c3679cf Mon Sep 17 00:00:00 2001
From: qqeasonchen
Date: Mon, 30 Sep 2019 16:39:18 +0800
Subject: [PATCH 16/26] add unit test of reply
---
.../consumer/DefaultMQPushConsumerTest.java | 128 ++++++++++++++++++
.../client/utils/MessageUtilsTest.java | 10 ++
2 files changed, 138 insertions(+)
diff --git a/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumerTest.java b/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumerTest.java
index e6f0e86688..a2a469ebfa 100644
--- a/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumerTest.java
+++ b/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumerTest.java
@@ -19,12 +19,16 @@ package org.apache.rocketmq.client.consumer;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.net.InetSocketAddress;
+import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.ConsumeOrderlyContext;
@@ -33,6 +37,7 @@ import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.consumer.listener.MessageListenerOrderly;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
+import org.apache.rocketmq.client.hook.SendMessageContext;
import org.apache.rocketmq.client.impl.CommunicationMode;
import org.apache.rocketmq.client.impl.FindBrokerResult;
import org.apache.rocketmq.client.impl.MQClientAPIImpl;
@@ -46,11 +51,23 @@ import org.apache.rocketmq.client.impl.consumer.PullRequest;
import org.apache.rocketmq.client.impl.consumer.PullResultExt;
import org.apache.rocketmq.client.impl.consumer.RebalancePushImpl;
import org.apache.rocketmq.client.impl.factory.MQClientInstance;
+import org.apache.rocketmq.client.impl.producer.DefaultMQProducerImpl;
+import org.apache.rocketmq.client.impl.producer.TopicPublishInfo;
+import org.apache.rocketmq.client.producer.SendCallback;
+import org.apache.rocketmq.client.producer.SendResult;
+import org.apache.rocketmq.client.producer.SendStatus;
+import org.apache.rocketmq.common.message.Message;
+import org.apache.rocketmq.common.message.MessageAccessor;
import org.apache.rocketmq.common.message.MessageClientExt;
+import org.apache.rocketmq.common.message.MessageConst;
import org.apache.rocketmq.common.message.MessageDecoder;
import org.apache.rocketmq.common.message.MessageExt;
import org.apache.rocketmq.common.message.MessageQueue;
import org.apache.rocketmq.common.protocol.header.PullMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.header.SendMessageRequestHeader;
+import org.apache.rocketmq.common.protocol.route.BrokerData;
+import org.apache.rocketmq.common.protocol.route.QueueData;
+import org.apache.rocketmq.common.protocol.route.TopicRouteData;
import org.apache.rocketmq.remoting.exception.RemotingException;
import org.junit.After;
import org.junit.Assert;
@@ -66,8 +83,10 @@ import org.powermock.modules.junit4.PowerMockRunner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Fail.failBecauseExceptionWasNotThrown;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.nullable;
@@ -123,6 +142,10 @@ public class DefaultMQPushConsumerTest {
field.setAccessible(true);
field.set(mQClientFactory, mQClientAPIImpl);
+ field = DefaultMQProducerImpl.class.getDeclaredField("mQClientFactory");
+ field.setAccessible(true);
+ field.set(mQClientFactory.getDefaultMQProducer().getDefaultMQProducerImpl(), mQClientFactory);
+
pullAPIWrapper = spy(new PullAPIWrapper(mQClientFactory, consumerGroup, false));
field = DefaultMQPushConsumerImpl.class.getDeclaredField("pullAPIWrapper");
field.setAccessible(true);
@@ -256,6 +279,64 @@ public class DefaultMQPushConsumerTest {
}
}
+ @Test
+ public void testReplyMessageSync() throws RemotingException, InterruptedException, MQBrokerException, MQClientException, NoSuchFieldException {
+ when(mQClientAPIImpl.sendMessage(anyString(), anyString(), any(Message.class), any(SendMessageRequestHeader.class), anyLong(), any(CommunicationMode.class),
+ nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class))).thenCallRealMethod();
+ when(mQClientAPIImpl.sendMessage(anyString(), anyString(), any(Message.class), any(SendMessageRequestHeader.class), anyLong(), any(CommunicationMode.class),
+ nullable(SendCallback.class), nullable(TopicPublishInfo.class), nullable(MQClientInstance.class), anyInt(), nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class)))
+ .thenReturn(createSendResult(SendStatus.SEND_OK));
+
+ when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute());
+
+ SendResult sendResult = pushConsumer.reply(createRequestMessage(), new byte[]{'a'}, 3000);
+ assertThat(sendResult.getSendStatus()).isEqualTo(SendStatus.SEND_OK);
+ assertThat(sendResult.getOffsetMsgId()).isEqualTo("12345");
+ assertThat(sendResult.getQueueOffset()).isEqualTo(456L);
+ }
+
+ @Test
+ public void testReplyMessageASync() throws RemotingException, InterruptedException, MQBrokerException, MQClientException, NoSuchFieldException {
+ when(mQClientAPIImpl.sendMessage(anyString(), anyString(), any(Message.class), any(SendMessageRequestHeader.class), anyLong(), any(CommunicationMode.class),
+ nullable(SendCallback.class), nullable(TopicPublishInfo.class), nullable(MQClientInstance.class), anyInt(), nullable(SendMessageContext.class), any(DefaultMQProducerImpl.class)))
+ .thenAnswer(new Answer