两篇精彩的文章:
rocketmq通过netty获取到消息请求后,直接掉处理模块,比如:SendMessageProcessor
这个处理类主要负责处理客户端发送消息的请求。
这个类实现了com.alibaba.rocketmq.remoting.netty.NettyRequestProcessor接口。这个接口下一共两个方法:
RemotingCommand processRequest(ChannelHandlerContext ctx, RemotingCommand request)
throws Exception;
boolean rejectRequest();
加粗的方法是我们接下来要讲的方法。
它同时还继承了com.alibaba.rocketmq.broker.processor.AbstractSendMessageProcessor。
我们先看一下这个过程的调用链:
这里有一篇博客写的特别好:http://www.cnblogs.com/sunshine-2015/p/6291116.html
再次基础之上补充一点点东西。
首先进入SendMessageProcessor类的第一个方法是:
这个类什么时候被调用的呢?肯定是netty通信模块接收到消息后调用了,具体实在这里:
就是箭头所指的地方调用的上面那个方法。
我们看一下完整的从netty通信模块接收消息到这里的整个过程:
现在就到了我们非常熟悉的Handler了。
这里从下往上看会更加的直观。
好了,我们接着往消息存储走。
我们进入这个方法:
private RemotingCommand sendMessage(final ChannelHandlerContext ctx, // final RemotingCommand request, // final SendMessageContext sendMessageContext, // final SendMessageRequestHeader requestHeader) throwsRemotingCommandException {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());if(log.isDebugEnabled()) {
log.debug("receive SendMessage request command, " +request);
}final long startTimstamp = this.brokerController.getBrokerConfig().getStartAcceptSendRequestTimeStamp();if (this.brokerController.getMessageStore().now()
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark(String.format("broker unable to service, until %s", UtilAll.timeMillisToHumanString2(startTimstamp)));returnresponse;
}
response.setCode(-1);super.msgCheck(ctx, requestHeader, response);if (response.getCode() != -1) {returnresponse;
}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();
}int sysFlag =requestHeader.getSysFlag();if (TopicFilterType.MULTI_TAG ==topicConfig.getTopicFilterType()) {
sysFlag|=MessageSysFlag.MultiTagsFlag;
}
String newTopic=requestHeader.getTopic();if ((null != newTopic &&newTopic.startsWith(MixAll.RETRY_GROUP_TOPIC_PREFIX))) {
String groupName=newTopic.substring(MixAll.RETRY_GROUP_TOPIC_PREFIX.length());
SubscriptionGroupConfig subscriptionGroupConfig=
this.brokerController.getSubscriptionGroupManager().findSubscriptionGroupConfig(groupName);if (null ==subscriptionGroupConfig) {
response.setCode(ResponseCode.SUBSCRIPTION_GROUP_NOT_EXIST);
response.setRemark("subscription group not exist, " + groupName + " " +FAQUrl.suggestTodo(FAQUrl.SUBSCRIPTION_GROUP_NOT_EXIST));returnresponse;
}int maxReconsumeTimes =subscriptionGroupConfig.getRetryMaxTimes();if (request.getVersion() >=MQVersion.Version.V3_4_9.ordinal()) {
maxReconsumeTimes=requestHeader.getMaxReconsumeTimes();
}int reconsumeTimes =requestHeader.getReconsumeTimes();if (reconsumeTimes >=maxReconsumeTimes) {
newTopic=MixAll.getDLQTopic(groupName);
queueIdInt= Math.abs(this.random.nextInt() % 99999999) %DLQ_NUMS_PER_GROUP;
topicConfig= this.brokerController.getTopicConfigManager().createTopicInSendMessageBackMethod(newTopic, // DLQ_NUMS_PER_GROUP, // PermName.PERM_WRITE, 0);if (null ==topicConfig) {
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("topic[" + newTopic + "] not exist");returnresponse;
}
}
}
MessageExtBrokerInner msgInner= newMessageExtBrokerInner();
msgInner.setTopic(newTopic);
msgInner.setBody(body);
msgInner.setFlag(requestHeader.getFlag());
MessageAccessor.setProperties(msgInner, MessageDecoder.string2messageProperties(requestHeader.getProperties()));
msgInner.setPropertiesString(requestHeader.getProperties());
msgInner.setTagsCode(MessageExtBrokerInner.tagsString2tagsCode(topicConfig.getTopicFilterType(), msgInner.getTags()));
msgInner.setQueueId(queueIdInt);
msgInner.setSysFlag(sysFlag);
msgInner.setBornTimestamp(requestHeader.getBornTimestamp());
msgInner.setBornHost(ctx.channel().remoteAddress());
msgInner.setStoreHost(this.getStoreHost());
msgInner.setReconsumeTimes(requestHeader.getReconsumeTimes()== null ? 0: requestHeader.getReconsumeTimes());if (this.brokerController.getBrokerConfig().isRejectTransactionMessage()) {
String traFlag=msgInner.getProperty(MessageConst.PROPERTY_TRANSACTION_PREPARED);if (traFlag != null) {
response.setCode(ResponseCode.NO_PERMISSION);
response.setRemark("the broker[" + this.brokerController.getBrokerConfig().getBrokerIP1() + "] sending transaction message is forbidden");returnresponse;
}
}
// 前面是一些系统检查和数据准备,下面进入消息存储环节。
PutMessageResult putMessageResult= this.brokerController.getMessageStore().putMessage(msgInner);
// 锚点putMessageif (putMessageResult != null) {boolean sendOK = false;switch(putMessageResult.getPutMessageStatus()) {//Success
casePUT_OK:
sendOK= true;
response.setCode(ResponseCode.SUCCESS);break;caseFLUSH_DISK_TIMEOUT:
response.setCode(ResponseCode.FLUSH_DISK_TIMEOUT);
sendOK= true;break;caseFLUSH_SLAVE_TIMEOU