(转载)【RocketMQ 课程笔记】9.生产者启动流程与消息发送流程
生产者启动流程与消息发送流程
生产者概述
发送消息的一方被称为生产者,它在整个RocketMQ的生产和消费体系中扮演的角色。
- 生产者组:一个逻辑概念,在使用生产者实例的时候需要指定一个组名。一个生产者组可以生产多个Topic的消息。
- 生产者实例:一个生产者组部署了多个进程,每个进程都可以称为一个生产者实例。
- Topic:主题名字,一个Topic由若干Queue组成。
- RocketMQ 客户端中的生产者有两个独立实现类:
- org.apache.rocketmq.client.producer.DefaultMQProducer
- org.apache.rocketmq.client.producer.TransactionMQProducer。
- 前者用于生产普通消息、顺序消息、单向消息、批量消息、延迟消息,后者主要用于生产事务消息。
消息的结构(了解一下)

生产者启动流程
图片来源:RocketMQ(二)-生产者启动流程
涉及的类
DefaultMQProducer:默认生产者实现类
DefaultMQProducerImpl:默认生产者的具体实现类,被DefaultMQProducer引用
MQClientInstance:MQ客户端实例,MQClientInstance包含了生产者与消费者需要的所有底层功能。
关键启动流程
- 调用producer.start()开始启动生产者实例,实例状态为CREATE_JUST,生产者可用状态为“失败”
//ProducerSample01 DefaultMQProducer producer = new DefaultMQProducer("pg1"); producer.setNamesrvAddr("192.168.31.103:9876"); try { producer.start(); ... }. ..
- 校验生产者实例设置的各种参数。比如生产者组名是否为空、是否满足命名规则、长度是否满足等。
- 执行changeInstanceNameToPID()方法。校验instance name,如果是默认名字则将其修改为进程id
//DefaultMQProducerImpl public void changeInstanceNameToPID() { if (this.instanceName.equals("DEFAULT")) { this.instanceName = UtilAll.getPid() + "#" + System.nanoTime(); } }
-
创建MQClientInstance实例并初始化,按MQClientInstance负责NameSrv通信获取Broker配置、启动各种服务模块、开启各种定时任务
-
MQClientInstance初始化完毕,生产者启动完毕
消息发送流程
RocketMQ客户端的消息发送通常分为以下3层:
-
业务层:通常指直接调用RocketMQ Client发送API的业务代码。
-
消息处理层:指RocketMQ Client获取业务发送的消息对象后,一系列的参数检查、消息发送准备、参数包装等操作。
-
通信层:指RocketMQ基于Netty封装的一个RPC通信服务,RocketMQ的各个组件之间的通信全部使用该通信层。
消息发送步骤
- 调用defaultMQProducer.send()方法准备发送消息。
for(int i = 0 ; i< 10000 ; i++) { String data = "{\"title\":\"X市2021年度第四季度税务汇总数据\"}"; Message message = new Message("tax-data", "2021S4", data.getBytes()); SendResult result = producer.send(message); System.out.println("消息已发送:MsgId:" + result.getMsgId() + ",发送状态:" + result.getSendStatus()); }
- 通过设置的发送超时时间,默认3秒
- 调用 defaultMQProducerImpl.sendDefaultImpl() 设置发送方式,可选值 ASYNC(异步) | ONEWAY(单向)| SYNC(同步)
- defaultMQProducerImpl.sendKernelImpl()用于控制发送过程
- 前置检查
- 选择Queue进行发送
- 可靠发送
- 发送结果处理
- 根据前面设置的CommunicationMode(通信模式),MQClientAPIImpl.sendMessage()调用remotingClient对象不同的方法完成通信。
switch (communicationMode) { case ONEWAY: //单向通道方法 this.remotingClient.invokeOneway(addr, request, timeoutMillis); return null; case ASYNC: final AtomicInteger times = new AtomicInteger(); long costTimeAsync = System.currentTimeMillis() - beginStartTime; if (timeoutMillis < costTimeAsync) { throw new RemotingTooMuchRequestException("sendMessage call timeout"); } // 异步传输 this.sendMessageAsync(addr, brokerName, msg, timeoutMillis - costTimeAsync, request, sendCallback, topicPublishInfo, instance, retryTimesWhenSendFailed, times, context, producer); return null; case SYNC: long costTimeSync = System.currentTimeMillis() - beginStartTime; if (timeoutMillis < costTimeSync) { throw new RemotingTooMuchRequestException("sendMessage call timeout"); } // 同步调用 return this.sendMessageSync(addr, brokerName, msg, timeoutMillis - costTimeSync, request); default: assert false; break; }
上述三个方法最终都是通过remotingClient提供的invokeXXX方法完成与Broker的通信,底层基于Netty框架实现异步网络传输。
- remotingClient.invokeSync //异步
- remotingClient.invokeAsync //同步
- remotingClient.invokeOneway //单向
本文作者:JamKing
本文链接:https://www.cnblogs.com/JamKing/p/16693892.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
,
标签:
,
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步