前言
围绕 defaultMQProducer.send(message) 这行代码展开分析。
源码解析
经过下面的一系列代码分析,RocketMQ发送消息的底层借助Netty的Channel#writeAndFlush(…)方法实现。
通过defaultMQProducer.setSendMsgTimeout(int timeout)方法改变默认的发送消息的超时时间。默认是3秒。
通过第二个参数CommunicationMode.SYNC,传递同步的通信方式。
private SendResult sendDefaultImpl(
Message msg,
final CommunicationMode communicationMode,
final SendCallback sendCallback,
final long timeout
) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {
/* 确保ServiceState是running状态 */
this.makeSureStateOK();
/* 要求消息体不为空、消息大小不超过消息最大的大小(默认是4MB)*/
/* 要求topic不为空,长度不能>=255,不能是TBW102,不能包含非法字符 */
Validators.checkMessage(msg, this.defaultMQProducer);
.....
TopicPublishInfo topicPublishInfo = this.tryToFindTopicPublishInfo(msg.getTopic());
/* ok() : TopicPublishInfo#ArrayList<MessageQueue>属性有元素 */
if (topicPublishInfo != null && topicPublishInfo.ok()) {
.....
/* 同步发送的生产者的重试次数为1 */
int timesTotal = communicationMode == CommunicationMode.SYNC ? 1 + this.defaultMQProducer.getRetryTimesWhenSendFailed() : 1;
int times = 0;
String[] brokersSent = new String[timesTotal];
for (; times < timesTotal; times++) {
/* MQFaultStrategy选取一个MessageQueue */
MessageQueue mqSelected = this.selectOneMessageQueue(topicPublishInfo, null);
if (mqSelected != null) {
mq = mqSelected;
brokersSent[times] = mq.getBrokerName();
......
/* 发送消息的核心方法 */
sendResult = this.sendKernelImpl(msg, mq, communicationMode, sendCallback, topicPublishInfo, timeout - costTime);
......
switch (communicationMode) {
.....
case SYNC:
if (sendResult.getSendStatus() != SendStatus.SEND_OK) {
/* Indicate whether to retry another broker on sending failure internally. */
if (this.defaultMQProducer.isRetryAnotherBrokerWhenNotStoreOK()