以下为RocketMQ—生产者系列文章索引:
1:启动流程(本文)
2:路由动态更新
3:发送方式分析+消息类型区别
4:生产者消息的发送流程
5:路由队列选择,客户端冗错策略(问题答疑)
一、Producer介绍
Producer 是 RocketMQ 消息的投递者,负责生产消息。
它会与NameServer集群中的其中一个节点(随机)建立长连接(Keep-alive),定期从NameServer读取Topic路由信息,将路由信息保存在本地内存中;
它向提供Topic服务的Master Broker建立长连接,且定时向Master Broker发送心跳;
它只会向Master Broker发送消息,从Message Queue列表中选择合适的Queue发送消息,实现负载均衡;
它支持发送消息类型有多种,例如:普通消息、事物消息、定时消息等;
它发送消息的方式支持三种:同步、异步、单向方式等.
可简单查看生产端与Master Broker 和NameServer简单交互图:
备注:生产者还可向broker查询消息等其他功能交互。
二、生产者启动流程:
在了解具体生产启动流程之前,我们先提出出几个问题,带着问题去分析源码:
-
消息生产者启动时具体做了什么?
-
一个应用需要发送多个topic,不同topic需要发送到不同集群的broker,如何处理?
我们可先了解和分析生产者相关的类图关系:
从类图中可以看出,MQProducer有两种实现方式。
一个是 DefaultMQProducer(非事务消息生产者);
一个是 TransactionMQProducer(支持事务消息);
接下来先对接个类核心参数或方法进行简单分析:
2.1 MqAdmin
MqAdmin:核心方法解析(Mq管理基础接口)
//创建一个主题
void createTopic(final String key, final String newTopic, final int queueNum) throws MQClientException;
//根据 时间戳从队列中 查找其偏移量
long searchOffset(final MessageQueue mq, final long timestamp) throws MQClientException;
//查找该消息 队列中 最大的物理偏移量
long maxOffset(final MessageQueue mq) throws MQClientException;
//查找该消息队列中最小物理偏移量。
long minOffset(final MessageQueue mq) throws MQClientException;
//获取最早的存储消息时间
long earliestMsgStoreTime(final MessageQueue mq) throws MQClientException;
//根据消息偏移量查找消息
MessageExt viewMessage(final String offsetMsgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException;
//根据条件查询消息
QueryResult queryMessage(final String topic, final String key, final int maxNum, final long begin, final long end) throws MQClientException, InterruptedException;
//根据 主题 与 消息ID 查找消息 。
MessageExt viewMessage(String topic, String msgId) throws RemotingException, MQBrokerException, InterruptedException, MQClientException;
2.2 核心方法解析
MQProducer:核心方法解析(生产者基础接口):
//启动
void start() throws MQClientException;
//关闭
void shutdown();
//根据topic获取对应队列信息
List<MessageQueue> fetchPublishMessageQueues(final String topic) throws MQClientException;
//同步-消息发送
SendResult send(final Message msg, final MessageQueue mq) throws MQClientException,RemotingException, MQBrokerException, InterruptedException;
//异步-消息发送
void send(final Message msg, final MessageQueueSelector selector, final Object arg, final SendCallback sendCallback) throws MQClientException, RemotingException, InterruptedException;
//同步-选择队列消息发送
SendResult send(final Message msg, final MessageQueueSelector selector, final Object arg, final long timeout) throws MQClientException, RemotingException, MQBrokerException,InterruptedException;
//单向-消息发送
void sendOneway(final Message msg, final MessageQueue mq) throws MQClientException, RemotingException, InterruptedException;
//事务消息-发送
TransactionSendResult sendMessageInTransaction(final Message msg, final Object arg) throws MQClientException;
//批量消息-发送
SendResult send(final Collection<Message> msgs) throws MQClientException, RemotingException, MQBrokerException, InterruptedException;
备注:其中启动start()和关闭shutdown()表示生产者的启动和关闭、
2.3 clientConfig
clientConfig:核心属性方法解析(客户端配置)
//nameServer-地址,默认从:系统属性:rocketmq.namesrv.addr 或 环境变量:NAMESRV_ADDR 中获取
private String namesrvAddr = System.getProperty(MixAll.NAMESRV_ADDR_PROPERTY, System.getenv(MixAll.NAMESRV_ADDR_ENV));
//实例名字,默认:DEFAULT 或者 系统属性-rocketmq.client.name
private String instanceName = System.getProperty("rocketmq.client.name", "DEFAULT");
//构建 mq客户端的 id,例子:ip@instanceName@unitName : 172.16.62.75@19312@unitName
public String buildMQClientId() {
StringBuilder sb = new StringBuilder();
sb.append(this.getClientIP());
sb.append("@");
sb.append(this.getInstanceName());
if (!UtilAll.isBlank(this.unitName)) {
sb.append("@");
sb.append(this.unitName);
}
return sb.toString();
}
//设置namesrv地址
public void setNamesrvAddr(String namesrvAddr) {
this.namesrvAddr = namesrvAddr;
}
备注:namesrvAddr表示nameServer地址,可调用setNamesrvAddr方法设置,或者通过环境变量、系统属性设置;buildMQClientId表示设置生产者Id.