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() { + @Override public Object answer(InvocationOnMock mock) throws Throwable { + CommunicationMode communicationMode = mock.getArgument(5); + SendCallback sendCallback = mock.getArgument(6); + SendResult sendResult = createSendResult(SendStatus.SEND_OK); + switch (communicationMode) { + case SYNC: + return sendCallback; + case ASYNC: + case ONEWAY: + if (sendCallback != null) { + sendCallback.onSuccess(sendResult); + } + } + return null; + } + }); + when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute()); + + final CountDownLatch countDownLatch = new CountDownLatch(1); + final AtomicBoolean replySuccess = new AtomicBoolean(false); + pushConsumer.reply(createRequestMessage(), new byte[] {'a'}, new SendCallback() { + @Override public void onSuccess(SendResult sendResult) { + assertThat(sendResult.getSendStatus()).isEqualTo(SendStatus.SEND_OK); + assertThat(sendResult.getOffsetMsgId()).isEqualTo("12345"); + assertThat(sendResult.getQueueOffset()).isEqualTo(456L); + countDownLatch.countDown(); + replySuccess.set(true); + } + + @Override public void onException(Throwable e) { + countDownLatch.countDown(); + } + }, 3000); + countDownLatch.await(3000, TimeUnit.MILLISECONDS); + assertTrue(replySuccess.get()); + } + private DefaultMQPushConsumer createPushConsumer() { DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer(consumerGroup); pushConsumer.registerMessageListener(new MessageListenerConcurrently() { @@ -294,4 +375,51 @@ public class DefaultMQPushConsumerTest { } return new PullResultExt(pullStatus, requestHeader.getQueueOffset() + messageExtList.size(), 123, 2048, messageExtList, 0, outputStream.toByteArray()); } + + private SendResult createSendResult(SendStatus sendStatus) { + SendResult sendResult = new SendResult(); + sendResult.setMsgId("12345"); + sendResult.setOffsetMsgId("12345"); + sendResult.setQueueOffset(456); + sendResult.setSendStatus(sendStatus); + sendResult.setRegionId("HZ"); + return sendResult; + } + + public static TopicRouteData createTopicRoute() { + TopicRouteData topicRouteData = new TopicRouteData(); + + topicRouteData.setFilterServerTable(new HashMap>()); + List brokerDataList = new ArrayList(); + BrokerData brokerData = new BrokerData(); + brokerData.setBrokerName("BrokerA"); + brokerData.setCluster("DefaultCluster"); + HashMap brokerAddrs = new HashMap(); + brokerAddrs.put(0L, "127.0.0.1:10911"); + brokerData.setBrokerAddrs(brokerAddrs); + brokerDataList.add(brokerData); + topicRouteData.setBrokerDatas(brokerDataList); + + List queueDataList = new ArrayList(); + QueueData queueData = new QueueData(); + queueData.setBrokerName("BrokerA"); + queueData.setPerm(6); + queueData.setReadQueueNums(3); + queueData.setWriteQueueNums(4); + queueData.setTopicSynFlag(0); + queueDataList.add(queueData); + topicRouteData.setQueueDatas(queueDataList); + + return topicRouteData; + } + + private Message createRequestMessage() { + Message requestMessage = new Message(); + Map map = new HashMap(); + map.put(MessageConst.PROPERTY_MESSAGE_REPLY_TO, "reply_to_who"); + map.put(MessageConst.PROPERTY_CLUSTER, "DefaultCluster"); + map.put(MessageConst.PROPERTY_MESSAGE_TTL, "3000"); + MessageAccessor.setProperties(requestMessage, map); + return requestMessage; + } } 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 406979c9f8..7847e7ee35 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 @@ -49,6 +49,16 @@ public class MessageUtilsTest { } } + @Test + public void testCreateReplyMessage_reqMsgIsNull() throws MQClientException { + try { + Message msg = MessageUtil.createReplyMessage(null, new byte[] {'a'}); + failBecauseExceptionWasNotThrown(MQClientException.class); + } catch (MQClientException e) { + assertThat(e).hasMessageContaining("create reply message fail, requestMessage cannot be null."); + } + } + private Message createReplyMessage(String clusterName) { Message requestMessage = new Message(); Map map = new HashMap(); From 18e44c2bbc11c60e451e548a90dea1bba590497e Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Sat, 12 Oct 2019 16:53:54 +0800 Subject: [PATCH 17/26] remove reply interface in consumer --- .../consumer/DefaultLitePullConsumer.java | 51 ------- .../consumer/DefaultMQPullConsumer.java | 49 ------- .../consumer/DefaultMQPushConsumer.java | 49 ------- .../consumer/DefaultLitePullConsumerImpl.java | 25 ---- .../consumer/DefaultMQPullConsumerImpl.java | 24 ---- .../consumer/DefaultMQPushConsumerImpl.java | 29 +--- .../client/impl/consumer/MQConsumerInner.java | 15 -- .../consumer/DefaultMQPushConsumerTest.java | 128 ------------------ .../example/rpc/ResponseConsumer.java | 19 ++- 9 files changed, 19 insertions(+), 370 deletions(-) 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 460558e407..99976d55d3 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,18 +22,13 @@ 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 { @@ -416,50 +411,4 @@ 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/consumer/DefaultMQPullConsumer.java b/client/src/main/java/org/apache/rocketmq/client/consumer/DefaultMQPullConsumer.java index 9e291b5638..0876a94e4c 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,10 +25,7 @@ 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; @@ -451,50 +448,4 @@ 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 8aa12a49a2..339f799f9a 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,15 +30,12 @@ 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; @@ -892,50 +889,4 @@ 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/consumer/DefaultLitePullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultLitePullConsumerImpl.java index d094f661f7..2c673a1b06 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,9 +53,6 @@ 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; @@ -63,7 +60,6 @@ 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; @@ -1079,25 +1075,4 @@ 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 { - 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/DefaultMQPullConsumerImpl.java b/client/src/main/java/org/apache/rocketmq/client/impl/consumer/DefaultMQPullConsumerImpl.java index 6c63ff494b..afd72a0800 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,9 +43,6 @@ 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; @@ -804,25 +801,4 @@ 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 20c59609ed..807e9c6d6f 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,6 +27,7 @@ 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; @@ -50,22 +51,20 @@ 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; @@ -76,7 +75,6 @@ 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; @@ -1175,25 +1173,4 @@ 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 { - 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 010d1db345..c2e8a1dfc4 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,18 +17,12 @@ 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 @@ -55,13 +49,4 @@ 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/test/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumerTest.java b/client/src/test/java/org/apache/rocketmq/client/consumer/DefaultMQPushConsumerTest.java index a2a469ebfa..e6f0e86688 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,16 +19,12 @@ 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; @@ -37,7 +33,6 @@ 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; @@ -51,23 +46,11 @@ 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; @@ -83,10 +66,8 @@ 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; @@ -142,10 +123,6 @@ 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); @@ -279,64 +256,6 @@ 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() { - @Override public Object answer(InvocationOnMock mock) throws Throwable { - CommunicationMode communicationMode = mock.getArgument(5); - SendCallback sendCallback = mock.getArgument(6); - SendResult sendResult = createSendResult(SendStatus.SEND_OK); - switch (communicationMode) { - case SYNC: - return sendCallback; - case ASYNC: - case ONEWAY: - if (sendCallback != null) { - sendCallback.onSuccess(sendResult); - } - } - return null; - } - }); - when(mQClientAPIImpl.getTopicRouteInfoFromNameServer(anyString(), anyLong())).thenReturn(createTopicRoute()); - - final CountDownLatch countDownLatch = new CountDownLatch(1); - final AtomicBoolean replySuccess = new AtomicBoolean(false); - pushConsumer.reply(createRequestMessage(), new byte[] {'a'}, new SendCallback() { - @Override public void onSuccess(SendResult sendResult) { - assertThat(sendResult.getSendStatus()).isEqualTo(SendStatus.SEND_OK); - assertThat(sendResult.getOffsetMsgId()).isEqualTo("12345"); - assertThat(sendResult.getQueueOffset()).isEqualTo(456L); - countDownLatch.countDown(); - replySuccess.set(true); - } - - @Override public void onException(Throwable e) { - countDownLatch.countDown(); - } - }, 3000); - countDownLatch.await(3000, TimeUnit.MILLISECONDS); - assertTrue(replySuccess.get()); - } - private DefaultMQPushConsumer createPushConsumer() { DefaultMQPushConsumer pushConsumer = new DefaultMQPushConsumer(consumerGroup); pushConsumer.registerMessageListener(new MessageListenerConcurrently() { @@ -375,51 +294,4 @@ public class DefaultMQPushConsumerTest { } return new PullResultExt(pullStatus, requestHeader.getQueueOffset() + messageExtList.size(), 123, 2048, messageExtList, 0, outputStream.toByteArray()); } - - private SendResult createSendResult(SendStatus sendStatus) { - SendResult sendResult = new SendResult(); - sendResult.setMsgId("12345"); - sendResult.setOffsetMsgId("12345"); - sendResult.setQueueOffset(456); - sendResult.setSendStatus(sendStatus); - sendResult.setRegionId("HZ"); - return sendResult; - } - - public static TopicRouteData createTopicRoute() { - TopicRouteData topicRouteData = new TopicRouteData(); - - topicRouteData.setFilterServerTable(new HashMap>()); - List brokerDataList = new ArrayList(); - BrokerData brokerData = new BrokerData(); - brokerData.setBrokerName("BrokerA"); - brokerData.setCluster("DefaultCluster"); - HashMap brokerAddrs = new HashMap(); - brokerAddrs.put(0L, "127.0.0.1:10911"); - brokerData.setBrokerAddrs(brokerAddrs); - brokerDataList.add(brokerData); - topicRouteData.setBrokerDatas(brokerDataList); - - List queueDataList = new ArrayList(); - QueueData queueData = new QueueData(); - queueData.setBrokerName("BrokerA"); - queueData.setPerm(6); - queueData.setReadQueueNums(3); - queueData.setWriteQueueNums(4); - queueData.setTopicSynFlag(0); - queueDataList.add(queueData); - topicRouteData.setQueueDatas(queueDataList); - - return topicRouteData; - } - - private Message createRequestMessage() { - Message requestMessage = new Message(); - Map map = new HashMap(); - map.put(MessageConst.PROPERTY_MESSAGE_REPLY_TO, "reply_to_who"); - map.put(MessageConst.PROPERTY_CLUSTER, "DefaultCluster"); - map.put(MessageConst.PROPERTY_MESSAGE_TTL, "3000"); - MessageAccessor.setProperties(requestMessage, map); - return requestMessage; - } } 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 f3b3fd1156..39012c8b3f 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,20 +24,30 @@ 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.producer.DefaultMQProducer; 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.remoting.exception.RemotingException; public class ResponseConsumer { public static void main(String[] args) throws InterruptedException, MQClientException { + String producerGroup = "please_rename_unique_group_name"; String consumerGroup = "please_rename_unique_group_name"; String topic = "RequestTopic"; + // create a producer to send reply message + DefaultMQProducer replyProducer = new DefaultMQProducer(producerGroup); + replyProducer.start(); + + // create consumer DefaultMQPushConsumer consumer = new DefaultMQPushConsumer(consumerGroup); consumer.setConsumeFromWhere(ConsumeFromWhere.CONSUME_FROM_LAST_OFFSET); - //recommend client configs + + // recommend client configs consumer.setPullTimeDelayMillsWhenException(0L); consumer.registerMessageListener(new MessageListenerConcurrently() { @@ -48,9 +58,12 @@ public class ResponseConsumer { try { System.out.printf("handle message: %s", msg.toString()); String replyTo = msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO); - byte[] replyContent = "reply message contents.".getBytes(); - SendResult replyResult = consumer.reply(msg, replyContent, 3000); + // create reply message with given util, do not create reply message by yourself + Message replyMessage = MessageUtil.createReplyMessage(msg, replyContent); + + // send reply message with producer + SendResult replyResult = replyProducer.send(replyMessage, 3000); System.out.printf("reply to %s , %s %n", replyTo, replyResult.toString()); } catch (MQClientException | RemotingException | MQBrokerException | InterruptedException e) { e.printStackTrace(); From a8c9fe681f01793c4eadb8ed779b1b092fbd7d79 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Sat, 12 Oct 2019 17:30:15 +0800 Subject: [PATCH 18/26] add err code when create reply message exception --- .../org/apache/rocketmq/client/common/ClientErrorCode.java | 1 + .../java/org/apache/rocketmq/client/utils/MessageUtil.java | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) 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 633670aecc..bc03b14df2 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 @@ -24,4 +24,5 @@ public class ClientErrorCode { 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; + public static final int CREATE_REPLY_MESSAGE_EXCEPTION = 10007; } \ No newline at end of file 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 1e975a9a98..6db470fd5d 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,6 +17,7 @@ package org.apache.rocketmq.client.utils; +import org.apache.rocketmq.client.common.ClientErrorCode; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.MixAll; import org.apache.rocketmq.common.message.Message; @@ -42,9 +43,9 @@ public class MessageUtil { return replyMessage; } else { - throw new MQClientException(-1, "create reply message fail, requestMessage error, property[" + MessageConst.PROPERTY_CLUSTER + "] is null."); + throw new MQClientException(ClientErrorCode.CREATE_REPLY_MESSAGE_EXCEPTION, "create reply message fail, requestMessage error, property[" + MessageConst.PROPERTY_CLUSTER + "] is null."); } } - throw new MQClientException(-1, "create reply message fail, requestMessage cannot be null."); + throw new MQClientException(ClientErrorCode.CREATE_REPLY_MESSAGE_EXCEPTION, "create reply message fail, requestMessage cannot be null."); } } From ebc0ede8593c1e4316cfa0b5b28a8eb884efb312 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Wed, 16 Oct 2019 15:34:17 +0800 Subject: [PATCH 19/26] optimization exception declare of request --- .../impl/producer/DefaultMQProducerImpl.java | 108 ++++++++---------- .../client/producer/DefaultMQProducer.java | 12 +- .../rocketmq/client/producer/MQProducer.java | 8 +- 3 files changed, 61 insertions(+), 67 deletions(-) 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 e740c834b4..c2736bc0cb 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 @@ -1377,32 +1377,28 @@ public class DefaultMQProducerImpl implements MQProducerInner { } } - public void request(Message msg, final RequestCallback requestCallback, long timeout) throws RemotingException { + public void request(Message msg, final RequestCallback requestCallback, long timeout) + throws RemotingException, InterruptedException, MQClientException, MQBrokerException { long beginTimestamp = System.currentTimeMillis(); 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); + 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) { - requestResponseFuture.setSendReqeustOk(true); - } + long cost = System.currentTimeMillis() - beginTimestamp; + 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 - cost); - } catch (Exception ex) { - log.warn("send request message to <{}> failed.", msg.getTopic(), ex); - throw new RemotingSendRequestException(msg.getTopic(), ex); - } + @Override + public void onException(Throwable e) { + requestResponseFuture.setCause(e); + requestFail(requestUniqId); + } + }, timeout - cost); } public Message request(final Message msg, final MessageQueueSelector selector, final Object arg, @@ -1447,32 +1443,29 @@ 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, InterruptedException, MQClientException, MQBrokerException { long beginTimestamp = System.currentTimeMillis(); 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); + 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) { - requestResponseFuture.setSendReqeustOk(true); - } + long cost = System.currentTimeMillis() - beginTimestamp; + 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 - cost); - @Override - public void onException(Throwable e) { - requestResponseFuture.setCause(e); - requestFail(requestUniqId); - } - }, timeout - cost); - } 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) @@ -1516,32 +1509,27 @@ public class DefaultMQProducerImpl implements MQProducerInner { } public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout) - throws RemotingException { + throws RemotingException, InterruptedException, MQClientException, MQBrokerException { long beginTimestamp = System.currentTimeMillis(); 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); + 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) { - requestResponseFuture.setSendReqeustOk(true); - } + long cost = System.currentTimeMillis() - beginTimestamp; + 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 - cost); - } catch (Exception ex) { - log.warn("send request message to <{}> failed.", msg.getTopic(), ex); - throw new RemotingSendRequestException(msg.getTopic(), ex); - } + @Override + public void onException(Throwable e) { + requestResponseFuture.setCause(e); + requestFail(requestUniqId); + } + }, null, timeout - cost); } private void requestFail(final String requestUniqId) { 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 fdb489eebd..faa79f54c9 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 @@ -579,6 +579,7 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer { * @throws RemotingException if there is any network-tier error. * @throws MQBrokerException if there is any broker error. * @throws InterruptedException if the thread is interrupted. + * @throws RequestTimeoutException if request timeout. */ @Override public Message request(final Message msg, final long timeout) throws RequestTimeoutException, MQClientException, @@ -601,10 +602,11 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer { * @throws MQClientException if there is any client error. * @throws RemotingException if there is any network-tier error. * @throws InterruptedException if the thread is interrupted. + * @throws MQBrokerException if there is any broker error. */ @Override public void request(final Message msg, final RequestCallback requestCallback, final long timeout) - throws MQClientException, RemotingException, InterruptedException, MQBrokerException, RequestTimeoutException { + throws MQClientException, RemotingException, InterruptedException, MQBrokerException { msg.setTopic(withNamespace(msg.getTopic())); this.defaultMQProducerImpl.request(msg, requestCallback, timeout); } @@ -621,6 +623,7 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer { * @throws RemotingException if there is any network-tier error. * @throws MQBrokerException if there is any broker error. * @throws InterruptedException if the thread is interrupted. + * @throws RequestTimeoutException if request timeout. */ @Override public Message request(final Message msg, final MessageQueueSelector selector, final Object arg, @@ -641,11 +644,12 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer { * @throws MQClientException if there is any client error. * @throws RemotingException if there is any network-tier error. * @throws InterruptedException if the thread is interrupted. + * @throws MQBrokerException if there is any broker error. */ @Override public void request(final Message msg, final MessageQueueSelector selector, final Object arg, final RequestCallback requestCallback, final long timeout) throws MQClientException, RemotingException, - InterruptedException { + InterruptedException, MQBrokerException { msg.setTopic(withNamespace(msg.getTopic())); this.defaultMQProducerImpl.request(msg, selector, arg, requestCallback, timeout); } @@ -660,6 +664,7 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer { * @throws RemotingException if there is any network-tier error. * @throws MQBrokerException if there is any broker error. * @throws InterruptedException if the thread is interrupted. + * @throws RequestTimeoutException if request timeout. */ @Override public Message request(final Message msg, final MessageQueue mq, final long timeout) @@ -678,10 +683,11 @@ public class DefaultMQProducer extends ClientConfig implements MQProducer { * @throws MQClientException if there is any client error. * @throws RemotingException if there is any network-tier error. * @throws InterruptedException if the thread is interrupted. + * @throws MQBrokerException if there is any broker error. */ @Override public void request(final Message msg, final MessageQueue mq, final RequestCallback requestCallback, long timeout) - throws MQClientException, RemotingException, InterruptedException { + throws MQClientException, RemotingException, InterruptedException, MQBrokerException { msg.setTopic(withNamespace(msg.getTopic())); 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 a837c3d232..c6cf4c9359 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 @@ -105,7 +105,7 @@ public interface MQProducer extends MQAdmin { RemotingException, MQBrokerException, InterruptedException; void request(final Message msg, final RequestCallback requestCallback, final long timeout) - throws RequestTimeoutException, MQClientException, RemotingException, InterruptedException, MQBrokerException; + throws MQClientException, RemotingException, InterruptedException, MQBrokerException; Message request(final Message msg, final MessageQueueSelector selector, final Object arg, final long timeout) throws RequestTimeoutException, MQClientException, RemotingException, MQBrokerException, @@ -113,12 +113,12 @@ public interface MQProducer extends MQAdmin { void request(final Message msg, final MessageQueueSelector selector, final Object arg, final RequestCallback requestCallback, - final long timeout) throws RequestTimeoutException, MQClientException, RemotingException, - InterruptedException; + final long timeout) throws MQClientException, RemotingException, + InterruptedException, MQBrokerException; 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; + throws MQClientException, RemotingException, MQBrokerException, InterruptedException; } From 9800afb002a9ad28244e3e5a04494b70b4a2c17f Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Wed, 16 Oct 2019 16:06:35 +0800 Subject: [PATCH 20/26] rename REQUEST_UNIQ_ID to CORRELATION_ID --- .../client/impl/ClientRemotingProcessor.java | 8 +-- .../impl/producer/DefaultMQProducerImpl.java | 59 +++++++++---------- .../client/producer/RequestFutureTable.java | 2 +- .../producer/RequestResponseFuture.java | 10 ++-- .../rocketmq/client/utils/MessageUtil.java | 4 +- .../rocketmq/common/message/MessageConst.java | 4 +- ...uestIdUtil.java => CorrelationIdUtil.java} | 4 +- 7 files changed, 45 insertions(+), 46 deletions(-) rename common/src/main/java/org/apache/rocketmq/common/utils/{RequestIdUtil.java => CorrelationIdUtil.java} (91%) 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 3bea2d8e5d..5cac5e832a 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 @@ -280,12 +280,12 @@ public class ClientRemotingProcessor implements NettyRequestProcessor { } private void processReplyMessage(MessageExt replyMsg) { - final String uniqueId = replyMsg.getUserProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID); - final RequestResponseFuture requestResponseFuture = RequestFutureTable.getRequestFutureTable().get(uniqueId); + final String correlationId = replyMsg.getUserProperty(MessageConst.PROPERTY_CORRELATION_ID); + final RequestResponseFuture requestResponseFuture = RequestFutureTable.getRequestFutureTable().get(correlationId); if (requestResponseFuture != null) { requestResponseFuture.putResponseMessage(replyMsg); - RequestFutureTable.getRequestFutureTable().remove(uniqueId); + RequestFutureTable.getRequestFutureTable().remove(correlationId); if (requestResponseFuture.getRequestCallback() != null) { requestResponseFuture.getRequestCallback().onSuccess(replyMsg); @@ -293,7 +293,7 @@ public class ClientRemotingProcessor implements NettyRequestProcessor { requestResponseFuture.putResponseMessage(replyMsg); } } else { - log.warn(String.format("receive reply message, but not matched any request, REQUEST_UNIQ_ID: %s", uniqueId)); + log.warn(String.format("receive reply message, but not matched any request, CorrelationId: %s", correlationId)); } } } 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 c2736bc0cb..c1c37737d8 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 @@ -85,13 +85,12 @@ 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.common.utils.CorrelationIdUtil; 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; @@ -1341,11 +1340,11 @@ public class DefaultMQProducerImpl implements MQProducerInner { 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); + final String correlationId = msg.getProperty(MessageConst.PROPERTY_CORRELATION_ID); try { - final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null); - RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture); + final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(correlationId, timeout, null); + RequestFutureTable.getRequestFutureTable().put(correlationId, requestResponseFuture); long cost = System.currentTimeMillis() - beginTimestamp; this.sendDefaultImpl(msg, CommunicationMode.ASYNC, new SendCallback() { @@ -1373,7 +1372,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { } return responseMessage; } finally { - RequestFutureTable.getRequestFutureTable().remove(requestUniqId); + RequestFutureTable.getRequestFutureTable().remove(correlationId); } } @@ -1381,10 +1380,10 @@ public class DefaultMQProducerImpl implements MQProducerInner { throws RemotingException, InterruptedException, MQClientException, MQBrokerException { long beginTimestamp = System.currentTimeMillis(); prepareSendRequest(msg, timeout); - final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID); + final String correlationId = msg.getProperty(MessageConst.PROPERTY_CORRELATION_ID); - final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback); - RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture); + final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(correlationId, timeout, requestCallback); + RequestFutureTable.getRequestFutureTable().put(correlationId, requestResponseFuture); long cost = System.currentTimeMillis() - beginTimestamp; this.sendDefaultImpl(msg, CommunicationMode.ASYNC, new SendCallback() { @@ -1396,7 +1395,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { @Override public void onException(Throwable e) { requestResponseFuture.setCause(e); - requestFail(requestUniqId); + requestFail(correlationId); } }, timeout - cost); } @@ -1406,11 +1405,11 @@ public class DefaultMQProducerImpl implements MQProducerInner { InterruptedException, RequestTimeoutException { long beginTimestamp = System.currentTimeMillis(); prepareSendRequest(msg, timeout); - final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID); + final String correlationId = msg.getProperty(MessageConst.PROPERTY_CORRELATION_ID); try { - final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null); - RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture); + final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(correlationId, timeout, null); + RequestFutureTable.getRequestFutureTable().put(correlationId, requestResponseFuture); long cost = System.currentTimeMillis() - beginTimestamp; this.sendSelectImpl(msg, selector, arg, CommunicationMode.ASYNC, new SendCallback() { @@ -1438,7 +1437,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { } return responseMessage; } finally { - RequestFutureTable.getRequestFutureTable().remove(requestUniqId); + RequestFutureTable.getRequestFutureTable().remove(correlationId); } } @@ -1447,10 +1446,10 @@ public class DefaultMQProducerImpl implements MQProducerInner { throws RemotingException, InterruptedException, MQClientException, MQBrokerException { long beginTimestamp = System.currentTimeMillis(); prepareSendRequest(msg, timeout); - final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID); + final String correlationId = msg.getProperty(MessageConst.PROPERTY_CORRELATION_ID); - final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback); - RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture); + final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(correlationId, timeout, requestCallback); + RequestFutureTable.getRequestFutureTable().put(correlationId, requestResponseFuture); long cost = System.currentTimeMillis() - beginTimestamp; this.sendSelectImpl(msg, selector, arg, CommunicationMode.ASYNC, new SendCallback() { @@ -1462,7 +1461,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { @Override public void onException(Throwable e) { requestResponseFuture.setCause(e); - requestFail(requestUniqId); + requestFail(correlationId); } }, timeout - cost); @@ -1472,11 +1471,11 @@ public class DefaultMQProducerImpl implements MQProducerInner { throws MQClientException, RemotingException, MQBrokerException, InterruptedException, RequestTimeoutException { long beginTimestamp = System.currentTimeMillis(); prepareSendRequest(msg, timeout); - final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID); + final String correlationId = msg.getProperty(MessageConst.PROPERTY_CORRELATION_ID); try { - final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, null); - RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture); + final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(correlationId, timeout, null); + RequestFutureTable.getRequestFutureTable().put(correlationId, requestResponseFuture); long cost = System.currentTimeMillis() - beginTimestamp; this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, new SendCallback() { @@ -1504,7 +1503,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { } return responseMessage; } finally { - RequestFutureTable.getRequestFutureTable().remove(requestUniqId); + RequestFutureTable.getRequestFutureTable().remove(correlationId); } } @@ -1512,10 +1511,10 @@ public class DefaultMQProducerImpl implements MQProducerInner { throws RemotingException, InterruptedException, MQClientException, MQBrokerException { long beginTimestamp = System.currentTimeMillis(); prepareSendRequest(msg, timeout); - final String requestUniqId = msg.getProperty(MessageConst.PROPERTY_REQUEST_UNIQ_ID); + final String correlationId = msg.getProperty(MessageConst.PROPERTY_CORRELATION_ID); - final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(requestUniqId, timeout, requestCallback); - RequestFutureTable.getRequestFutureTable().put(requestUniqId, requestResponseFuture); + final RequestResponseFuture requestResponseFuture = new RequestResponseFuture(correlationId, timeout, requestCallback); + RequestFutureTable.getRequestFutureTable().put(correlationId, requestResponseFuture); long cost = System.currentTimeMillis() - beginTimestamp; this.sendKernelImpl(msg, mq, CommunicationMode.ASYNC, new SendCallback() { @@ -1527,13 +1526,13 @@ public class DefaultMQProducerImpl implements MQProducerInner { @Override public void onException(Throwable e) { requestResponseFuture.setCause(e); - requestFail(requestUniqId); + requestFail(correlationId); } }, null, timeout - cost); } - private void requestFail(final String requestUniqId) { - RequestResponseFuture responseFuture = RequestFutureTable.getRequestFutureTable().remove(requestUniqId); + private void requestFail(final String correlationId) { + RequestResponseFuture responseFuture = RequestFutureTable.getRequestFutureTable().remove(correlationId); if (responseFuture != null) { responseFuture.setSendReqeustOk(false); responseFuture.putResponseMessage(null); @@ -1546,9 +1545,9 @@ public class DefaultMQProducerImpl implements MQProducerInner { } private void prepareSendRequest(final Message msg, long timeout) { - String requestUniqId = RequestIdUtil.createUniqueRequestId(); + String correlationId = CorrelationIdUtil.createCorrelationId(); String requestClientId = this.getmQClientFactory().getClientId(); - MessageAccessor.putProperty(msg, MessageConst.PROPERTY_REQUEST_UNIQ_ID, requestUniqId); + MessageAccessor.putProperty(msg, MessageConst.PROPERTY_CORRELATION_ID, correlationId); MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_REPLY_TO, requestClientId); MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_TTL, String.valueOf(timeout)); 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 6ce53119ea..3d4caa208b 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 @@ -45,7 +45,7 @@ public class RequestFutureTable { if (rep.isTimeout()) { it.remove(); rfList.add(rep); - log.warn("remove timeout request, REQUEST_UNIQ_ID={}" + rep.getRequestUniqId()); + log.warn("remove timeout request, CorrelationId={}" + rep.getCorrelationId()); } } 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 c476ba30f1..c54b236b16 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 @@ -22,7 +22,7 @@ import java.util.concurrent.TimeUnit; import org.apache.rocketmq.common.message.Message; public class RequestResponseFuture { - private final String requestUniqId; + private final String correlationId; private final RequestCallback requestCallback; private final long beginTimestamp = System.currentTimeMillis(); private final Message requestMsg = null; @@ -32,8 +32,8 @@ public class RequestResponseFuture { private volatile boolean sendRequestOk = true; private volatile Throwable cause = null; - public RequestResponseFuture(String requestUniqId, long timeoutMillis, RequestCallback requestCallback) { - this.requestUniqId = requestUniqId; + public RequestResponseFuture(String correlationId, long timeoutMillis, RequestCallback requestCallback) { + this.correlationId = correlationId; this.timeoutMillis = timeoutMillis; this.requestCallback = requestCallback; } @@ -63,8 +63,8 @@ public class RequestResponseFuture { this.countDownLatch.countDown(); } - public String getRequestUniqId() { - return requestUniqId; + public String getCorrelationId() { + return correlationId; } public long getTimeoutMillis() { 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 6db470fd5d..626b4525bb 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 @@ -30,14 +30,14 @@ public class MessageUtil { 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 correlationId = requestMessage.getProperty(MessageConst.PROPERTY_CORRELATION_ID); String ttl = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_TTL); replyMessage.setBody(body); 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_CORRELATION_ID, correlationId); MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_REPLY_TO, replyTo); MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TTL, ttl); 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 178e417c7a..f773c2b945 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,7 +45,7 @@ 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_CORRELATION_ID = "CORRELATION_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"; @@ -81,7 +81,7 @@ 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_CORRELATION_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); diff --git a/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java b/common/src/main/java/org/apache/rocketmq/common/utils/CorrelationIdUtil.java similarity index 91% rename from common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java rename to common/src/main/java/org/apache/rocketmq/common/utils/CorrelationIdUtil.java index 86c5096df5..86d1fd4d42 100644 --- a/common/src/main/java/org/apache/rocketmq/common/utils/RequestIdUtil.java +++ b/common/src/main/java/org/apache/rocketmq/common/utils/CorrelationIdUtil.java @@ -19,8 +19,8 @@ package org.apache.rocketmq.common.utils; import java.util.UUID; -public class RequestIdUtil { - public static String createUniqueRequestId() { +public class CorrelationIdUtil { + public static String createCorrelationId() { return UUID.randomUUID().toString(); } } From f16fd08c5e39101d93d83febeb29cbbddd8434e6 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Wed, 16 Oct 2019 17:15:11 +0800 Subject: [PATCH 21/26] rename REPLY_TO to REPLY_TO_CLIENT --- .../broker/processor/ReplyMessageProcessor.java | 6 +++--- .../broker/processor/ReplyMessageProcessorTest.java | 4 +--- .../client/impl/producer/DefaultMQProducerImpl.java | 2 +- .../apache/rocketmq/client/utils/MessageUtil.java | 8 ++++++-- .../rocketmq/client/utils/MessageUtilsTest.java | 12 ++++++++++-- .../apache/rocketmq/common/message/MessageConst.java | 4 ++-- .../rocketmq/example/rpc/ResponseConsumer.java | 2 +- 7 files changed, 24 insertions(+), 14 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 265c5c122f..565857a347 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 @@ -173,7 +173,7 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen 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); + String senderId = msg.getProperties().get(MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT); PushReplyResult pushReplyResult = new PushReplyResult(false); if (senderId != null) { @@ -207,9 +207,9 @@ public class ReplyMessageProcessor extends AbstractSendMessageProcessor implemen log.warn(pushReplyResult.getRemark()); } } else { - log.warn("REPLY_TO is null, can not reply message"); + log.warn(MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT + " is null, can not reply message"); pushReplyResult.setPushOk(false); - pushReplyResult.setRemark("reply message properties[" + MessageConst.PROPERTY_MESSAGE_REPLY_TO + "] is null"); + pushReplyResult.setRemark("reply message properties[" + MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT + "] is null"); } return pushReplyResult; } 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 a28f780601..94fd8f560d 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 @@ -30,7 +30,6 @@ 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; @@ -58,7 +57,6 @@ 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; @@ -126,7 +124,7 @@ public class ReplyMessageProcessorTest { requestHeader.setFlag(124); requestHeader.setReconsumeTimes(0); Map map = new HashMap(); - map.put(MessageConst.PROPERTY_MESSAGE_REPLY_TO, "127.0.0.1"); + map.put(MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT, "127.0.0.1"); requestHeader.setProperties(MessageDecoder.messageProperties2String(map)); return requestHeader; } 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 c1c37737d8..f2cc605b97 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 @@ -1548,7 +1548,7 @@ public class DefaultMQProducerImpl implements MQProducerInner { String correlationId = CorrelationIdUtil.createCorrelationId(); String requestClientId = this.getmQClientFactory().getClientId(); MessageAccessor.putProperty(msg, MessageConst.PROPERTY_CORRELATION_ID, correlationId); - MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_REPLY_TO, requestClientId); + MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT, requestClientId); MessageAccessor.putProperty(msg, MessageConst.PROPERTY_MESSAGE_TTL, String.valueOf(timeout)); boolean hasRouteData = this.getmQClientFactory().getTopicRouteTable().containsKey(msg.getTopic()); 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 626b4525bb..416ba44da3 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 @@ -29,7 +29,7 @@ public class MessageUtil { if (requestMessage != null) { Message replyMessage = new Message(); String cluster = requestMessage.getProperty(MessageConst.PROPERTY_CLUSTER); - String replyTo = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO); + String replyTo = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT); String correlationId = requestMessage.getProperty(MessageConst.PROPERTY_CORRELATION_ID); String ttl = requestMessage.getProperty(MessageConst.PROPERTY_MESSAGE_TTL); replyMessage.setBody(body); @@ -38,7 +38,7 @@ public class MessageUtil { replyMessage.setTopic(replyTopic); MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TYPE, MixAll.REPLY_MESSAGE_FLAG); MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_CORRELATION_ID, correlationId); - MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_REPLY_TO, replyTo); + MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT, replyTo); MessageAccessor.putProperty(replyMessage, MessageConst.PROPERTY_MESSAGE_TTL, ttl); return replyMessage; @@ -48,4 +48,8 @@ public class MessageUtil { } throw new MQClientException(ClientErrorCode.CREATE_REPLY_MESSAGE_EXCEPTION, "create reply message fail, requestMessage cannot be null."); } + + public static String getReplyToClient(final Message msg) { + return msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO_CLIENT); + } } 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 7847e7ee35..803e596fc8 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 @@ -35,7 +35,7 @@ public class MessageUtilsTest { 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_REPLY_TO_CLIENT)).isEqualTo("127.0.0.1"); assertThat(msg.getProperty(MessageConst.PROPERTY_MESSAGE_TTL)).isEqualTo("3000"); } @@ -59,10 +59,18 @@ public class MessageUtilsTest { } } + @Test + public void testGetReplyToClient() throws MQClientException { + Message msg = createReplyMessage("clusterName"); + String replyToClient = MessageUtil.getReplyToClient(msg); + assertThat(replyToClient).isNotNull(); + assertThat(replyToClient).isEqualTo("127.0.0.1"); + } + 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_MESSAGE_REPLY_TO_CLIENT, "127.0.0.1"); map.put(MessageConst.PROPERTY_CLUSTER, clusterName); map.put(MessageConst.PROPERTY_MESSAGE_TTL, "3000"); MessageAccessor.setProperties(requestMessage, map); 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 f773c2b945..5bdc846562 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 @@ -46,7 +46,7 @@ public class MessageConst { 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_CORRELATION_ID = "CORRELATION_ID"; - public static final String PROPERTY_MESSAGE_REPLY_TO = "REPLY_TO"; + public static final String PROPERTY_MESSAGE_REPLY_TO_CLIENT = "REPLY_TO_CLIENT"; 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"; @@ -82,7 +82,7 @@ public class MessageConst { STRING_HASH_SET.add(PROPERTY_CONSUME_START_TIMESTAMP); STRING_HASH_SET.add(PROPERTY_INSTANCE_ID); STRING_HASH_SET.add(PROPERTY_CORRELATION_ID); - STRING_HASH_SET.add(PROPERTY_MESSAGE_REPLY_TO); + STRING_HASH_SET.add(PROPERTY_MESSAGE_REPLY_TO_CLIENT); STRING_HASH_SET.add(PROPERTY_MESSAGE_TTL); STRING_HASH_SET.add(PROPERTY_REPLY_MESSAGE_ARRIVE_TIME); STRING_HASH_SET.add(PROPERTY_PUSH_REPLY_TIME); 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 39012c8b3f..5a53538b54 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 @@ -57,7 +57,7 @@ public class ResponseConsumer { for (MessageExt msg : msgs) { try { System.out.printf("handle message: %s", msg.toString()); - String replyTo = msg.getProperty(MessageConst.PROPERTY_MESSAGE_REPLY_TO); + String replyTo = MessageUtil.getReplyToClient(msg); byte[] replyContent = "reply message contents.".getBytes(); // create reply message with given util, do not create reply message by yourself Message replyMessage = MessageUtil.createReplyMessage(msg, replyContent); From 4fa263f75674ebeaf51a2e654af600cfefb599e3 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Wed, 16 Oct 2019 17:34:56 +0800 Subject: [PATCH 22/26] code style format --- .../java/org/apache/rocketmq/example/rpc/ResponseConsumer.java | 1 - 1 file changed, 1 deletion(-) 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 5a53538b54..c62c7d4eb6 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 @@ -29,7 +29,6 @@ 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.remoting.exception.RemotingException; From b6e4be83c7a4bddb56eedadd01e0a344ea429ff1 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Wed, 16 Oct 2019 21:22:09 +0800 Subject: [PATCH 23/26] fix unit test --- .../rocketmq/client/producer/DefaultMQProducerTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 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 991a572529..3811753573 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 @@ -398,13 +398,13 @@ public class DefaultMQProducerTest { try { producer.request(message, requestCallback, 3 * 1000L); - failBecauseExceptionWasNotThrown(RemotingSendRequestException.class); - } catch (RemotingSendRequestException e) { + failBecauseExceptionWasNotThrown(Exception.class); + } catch (Exception e) { ConcurrentHashMap responseMap = RequestFutureTable.getRequestFutureTable(); assertThat(responseMap).isNotNull(); for (Map.Entry entry : responseMap.entrySet()) { RequestResponseFuture future = entry.getValue(); - future.getRequestCallback().onException(new Throwable()); + future.getRequestCallback().onException(e); } } countDownLatch.await(3000L, TimeUnit.MILLISECONDS); From 01827c8dd3a4e375cdea4e802f93c802ec43ea83 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Mon, 21 Oct 2019 11:37:30 +0800 Subject: [PATCH 24/26] remove unused code and fix typo --- .../broker/processor/ReplyMessageProcessorTest.java | 3 +-- .../rocketmq/client/impl/ClientRemotingProcessor.java | 8 +++++--- 2 files changed, 6 insertions(+), 5 deletions(-) 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 94fd8f560d..85c775040f 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 @@ -71,8 +71,7 @@ public class ReplyMessageProcessorTest { private MessageStore messageStore; @Mock private Channel channel; - @Mock - private TransactionalMessageService transactionMsgService; + private String topic = "FooBar"; private String group = "FooBarGroup"; private ClientChannelInfo clientInfo; 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 5cac5e832a..c57e49bb61 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 @@ -83,7 +83,7 @@ public class ClientRemotingProcessor implements NettyRequestProcessor { return this.consumeMessageDirectly(ctx, request); case RequestCode.PUSH_REPLY_MESSAGE_TO_CLIENT: - return this.receiveReplyMssage(ctx, request); + return this.receiveReplyMessage(ctx, request); default: break; } @@ -222,7 +222,7 @@ public class ClientRemotingProcessor implements NettyRequestProcessor { return response; } - private RemotingCommand receiveReplyMssage(ChannelHandlerContext ctx, + private RemotingCommand receiveReplyMessage(ChannelHandlerContext ctx, RemotingCommand request) throws RemotingCommandException { final RemotingCommand response = RemotingCommand.createResponseCommand(null); @@ -293,7 +293,9 @@ public class ClientRemotingProcessor implements NettyRequestProcessor { requestResponseFuture.putResponseMessage(replyMsg); } } else { - log.warn(String.format("receive reply message, but not matched any request, CorrelationId: %s", correlationId)); + String bornHost = replyMsg.getBornHostString(); + log.warn(String.format("receive reply message, but not matched any request, CorrelationId: %s , reply from host: %s", + correlationId, bornHost)); } } } From 119feeedd40a109ead1e777d15f75e6ec1bd02b8 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Thu, 24 Oct 2019 10:19:40 +0800 Subject: [PATCH 25/26] use RemotingUtil to parse address --- .../client/impl/ClientRemotingProcessor.java | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) 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 c57e49bb61..b093b9531e 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 @@ -51,6 +51,7 @@ 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; +import org.apache.rocketmq.remoting.common.RemotingUtil; import org.apache.rocketmq.remoting.exception.RemotingCommandException; import org.apache.rocketmq.remoting.netty.NettyRequestProcessor; import org.apache.rocketmq.remoting.protocol.RemotingCommand; @@ -236,19 +237,11 @@ public class ClientRemotingProcessor implements NettyRequestProcessor { 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]))); + msg.setBornHost(RemotingUtil.string2SocketAddress(requestHeader.getBornHost())); } 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]))); + msg.setStoreHost(RemotingUtil.string2SocketAddress(requestHeader.getStoreHost())); } byte[] body = request.getBody(); From a314e17b751f92b4935fb650963c9ee02ce8aa48 Mon Sep 17 00:00:00 2001 From: qqeasonchen Date: Thu, 24 Oct 2019 10:46:00 +0800 Subject: [PATCH 26/26] remove unused import --- .../org/apache/rocketmq/client/impl/ClientRemotingProcessor.java | 1 - 1 file changed, 1 deletion(-) 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 b093b9531e..5861bc4baa 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 @@ -18,7 +18,6 @@ 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;