RocketMQ高手之路系列之五:RocketMQ之消息发送(二)

  • 消息发送基本流程

  • 总结

一、消息发送基本流程


在介绍消息发送流程之前,我们先来看下RocketMQ的架构图,如下所示:

在这里插入图片描述

架构图中的各个模块的大致作用在前几篇文章中已经介绍过了,这里不再进行赘述。主要通过架构图让大家对RocketMQ中的消息发送有个整体的理解。

消息的发送方式主要包括三种方式:

(1)同步方式;

(2)异步方式:

(3)Oneway方式;

消息的发送流程主要步骤为:消息验证、路由信息查找以及消息发送三个基本步骤。在DefaultMQProducer中可以查看到对应的消息发送方法,如下所示:

@Override

public SendResult send(

Message msg) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {

return this.defaultMQProducerImpl.send(msg);

}

@Override

public SendResult send(Message msg,

long timeout) throws MQClientException, RemotingException, MQBrokerException, InterruptedException {

return this.defaultMQProducerImpl.send(msg, timeout);

}

@Override

public void send(Message msg,

SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException {

this.defaultMQProducerImpl.send(msg, sendCallback);

}

大致的调用方式如下图所示:

在这里插入图片描述

消息发动的方式默认采用同步的方式进行,同时默认的超时时间为3s。在发送消息时,我们首先需要知道该消息要发送到哪里,这就像我们寄快递,需要先明确收件人是谁。那么在RocketMQ发送消息前会对消息进行基本的消息验证。确认消息是否符合发送要求。

Validators.checkMessage(msg, this.defaultMQProducer);

具体的代码如下所示:

public static void checkMessage(Message msg, DefaultMQProducer defaultMQProducer)

throws MQClientException {

//消息不能为空

if (null == msg) {

throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, “the message is null”);

}

// 主题不能为空

Validators.checkTopic(msg.getTopic());

// 消息的body不能为空

if (null == msg.getBody()) {

throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, “the message body is null”);

}

// 消息的body长度不能为0

if (0 == msg.getBody().length) {

throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL, “the message body length is zero”);

}

// 消息的body长度不能唱过最大长度4M

if (msg.getBody().length > defaultMQProducer.getMaxMessageSize()) {

throw new MQClientException(ResponseCode.MESSAGE_ILLEGAL,

"the message body size over max value, MAX: " + defaultMQProducer.getMaxMessageSize());

}

}

消息的校验没有问题则会调用tryToFindTopicPublishInfo(msg.getTopic())方法。我们需要获取主题的路由信息,通过路由信息我们才知道消息需要被投递到哪个具体的Broker节点之上。

我们来一起看下查找主题的路由信息方法,如下所示:

private TopicPublishInfo tryToFindTopicPublishInfo(final String topic) {

//先从本地缓存变量topicPublishInfoTable中先get一次

TopicPublishInfo topicPublishInfo = this.topicPublishInfoTable.get(topic);

if (null == topicPublishInfo || !topicPublishInfo.ok()) {

this.topicPublishInfoTable.putIfAbsent(topic, new TopicPublishInfo());

//然后从nameServer上更新topic路由信息

this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic);

//然后再从本地缓存变量topicPublishInfoTable中再get一次

topicPublishInfo = this.topicPublishInfoTable.get(topic);

}

if (topicPublishInfo.isHaveTopicRouterInfo() || topicPublishInfo.ok()) {

return topicPublishInfo;

} else {

//第一次的时候isDefault为false,第二次的时候default为true,即为用默认的topic的参数进行更新

this.mQClientFactory.updateTopicRouteInfoFromNameServer(topic, true, this.defaultMQProducer);

topicPublishInfo = this.topicPublishInfoTable.get(topic);

return topicPublishInfo;

}

}

在生产者中如果缓存了topic路由信息,路由信息中如果包含了消息队列,那么会进行路由信息的返回。如果没有缓存或者没有队列信息,那么就会向NameServer查询topic的路由信息。TopicPublishInfo属性如下所示:

public class TopicPublishInfo {

//是否是顺序消息

private boolean orderTopic = false;

//是否包含主题路由信息

private boolean haveTopicRouterInfo = false;

//主题队列的消息队列

private List messageQueueList = new ArrayList();

// 没选择一次消息队列,值自增1

private volatile ThreadLocalIndex sendWhichQueue = new ThreadLocalIndex();

private TopicRouteData topicRouteData;

public boolean isOrderTopic() {

return orderTopic;

}

public void setOrderTopic(boolean orderTopic) {

this.orderTopic = orderTopic;

}

public boolean ok() {

return null != this.messageQueueList && !this.messageQueueList.isEmpty();

}

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
在这里插入图片描述

ist.isEmpty();

}

最后

Java架构学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分析,高并发、高性能、分布式,性能优化,微服务 高级架构开发等等。

还有Java核心知识点+全套架构师学习资料和视频+一线大厂面试宝典+面试简历模板可以领取+阿里美团网易腾讯小米爱奇艺快手哔哩哔哩面试题+Spring源码合集+Java架构实战电子书+2021年最新大厂面试题。
[外链图片转存中…(img-xuD6WLHt-1714443896323)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值