从 消息发送 (Producer发送消息到Broker)、 消息存储 (Broker落盘逻辑)、 消息消费 (Consumer拉取/推送消息)三个核心流程切入分析RocketMQ的客户端、服务端源码。
本篇主要分析v5的客户端部分源码类
分析源码
rocketmq:https://github.com/apache/rocketmq.git
client:https://github.com/apache/rocketmq-clients/blob/master/README-CN.md
rocketmq-spring
<!--add dependency in pom.xml-->
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-spring-boot-starter</artifactId>
<version>${RELEASE.VERSION}</version>
</dependency>
使用的starter就是对rocketmq-spring包装了一层,https://rocketmq.apache.org/zh/docs/sdk/01overview/

旧版RocketMQ的client源码不太一样
- 如DefaultMQProducer 是旧版 RocketMQ Java 客户端的生产者抽象,实现是DefaultMQProducerImpl,采用传统的面向对象编程方式基于remotting协议,配置和使用相对固定。
- Producer是java新客户端的抽象,ProducerImpl 是新客户端的生产者实现,基于gRPC协议运用构建器模式进行初始化。
消息发送流程主要的类
这里分析基于gRPC之后的client源码。其中client和Broker通信发送消息的入口类RocketMQClientTemplate。
RocketMQClientTemplate类
RocketMQClientTemplate 是 RocketMQ 的 Spring 客户端模板类,继承 AbstractMessageSendingTemplate (Spring 消息发送抽象类),实现 DisposableBean (用于资源释放),核心功能是封装消息的 同步/异步发送 、 事务消息 、 消息接收与确认 等操作。
同步发送的核心入口是 syncSendGrpcMessage ,被以下方法调用:
- syncSendDelayMessage (延迟消息)
- syncSendFifoMessage (FIFO 顺序消息)
- syncSendNormalMessage (普通消息)
异步发送的核心入口是 asyncSend ,被以下方法调用:
- asyncSendWithObjectPayload (对象载荷)
- asyncSendWithStringPayload (字符串载荷)
- asyncSendWithBytePayload (字节数组载荷)
- asyncSendNormalMessage (普通异步消息)
- asyncSendFifoMessage (FIFO 异步消息)
- asyncSendDelayMessage (延迟异步消息)
主要的成员属性
// 构建Producer实例,producerBuilder.build()
// 可以设置topics、maxAttemps、setTransactionChecker、clientConfiguration等
private ProducerBuilder producerBuilder;
// 构建Consumer实例,consumerBuilder.build()
private SimpleConsumerBuilder simpleConsumerBuilder;
// 生产者抽象接口,指的是和Broker通信的生产者
private volatile Producer producer;
// 消费者抽象接口,指的是和Broker通信的消费者
private volatile SimpleConsumer simpleConsumer;
// 序列化器,支持MappingJackson2MessageConverter、MappingFastJsonMessageConverter、StringMessageConverter、ByteArrayMessageConverter
private RocketMQMessageConverter rocketMQMessageConverter = new RocketMQMessageConverter();
其中Producer是接口,生产者的抽象,包含三个send方法,对应三种将消息发送到Broker的类型
- 同步发送普通消息
- 同步发送事务消息
- 异步发送普通消息
SendReceipt send(Message message) throws ClientException;
SendReceipt send(Message message, Transaction transaction) throws ClientException;
CompletableFuture<SendReceipt> sendAsync(Message message);
ProducerBuilder的实现类ProducerBuilderImpl创建ProducerImpl实例,然后调用startAsync异步启动ProducerImpl,并等待处于可用状态。
// ProducerBuilderImpl
@Override
public Producer build() {
checkNotNull(clientConfiguration, "clientConfiguration has not been set yet");
final ProducerImpl producer = new ProducerImpl(clientConfiguration, topics, maxAttempts, checker);
producer.startAsync().awaitRunning();
return producer;
}
Producer以及Client类
ProducerImpl 类实现了 RocketMQ 生产者的核心功能,包括启动和关闭生产者、处理孤儿事务消息、发送消息等。通过继承 ClientImpl 类和实现 Producer 接口,该类提供了一个完整的生产者实现,支持同步和异步消息发送,以及事务消息处理。
ProducerImpl类继承ClientImpl类实现Producer接口,在ClientImpl类进行client、clientManager启动,然后做一些准备工作
- 启动ClientManager,ClientManager 提供一系列统一的 RPC 调用接口,覆盖消息发送、路由查询、心跳、消息确认、将消息发送到DLQ等核心操作。
- 从NameScvr拉取Broker的topic等信息
- 注册定时任务,定时30s从Broker更新topic等路由信息。路由信息被放入一个ConcurrentHashMap,key为topic,value为TopicRouteData。
ProducerImpl的属性,主要是记录一些发送消息的配置以及路由数据等
class ProducerImpl extends ClientImpl implements Producer {
//发布消息的配置信息。
protected final PublishingSettings publishingSettings;
// 一个并发映射,用于缓存主题的发布路由数据。
final ConcurrentMap<String/* topic */, PublishingLoadBalancer> publishingRouteDataCache;
// 事务检查器,用于处理事务消息。
private final TransactionChecker checker;
}
ProducerImpl实际启动调用ClientImpl的startUp方法
/**
* Start the rocketmq client and do some preparatory work.
*/
@Override
protected void startUp() throws Exception {
log.info("Begin to start the rocketmq client, clientId={}", clientId);
this.clientManager.startAsync().awaitRunning();
// Fetch topic route from remote.
log.info("Begin to fetch topic(s) route data from remote during client startup, clientId={}, topics={}",
clientId, topics);
for (String topic : topics) {
final ListenableFuture<TopicRouteData> future = fetchTopicRoute(topic);
future.get();
}
log.info("Fetch topic route data from remote successfully during startup, clientId={}, topics={}",
clientId, topics);
// Update route cache periodically.
final ScheduledExecutorService scheduler = clientManager.getScheduler();
this.updateRouteCacheFuture = scheduler.scheduleWithFixedDelay(() -> {
try {
updateRouteCache();
} catch (Throwable t) {
log.error("Exception raised while updating topic route cache, clientId={}", clientId, t);
}
}, 10, 30, TimeUnit.SECONDS);
log.info("The rocketmq client starts successfully, clientId={}", clientId);
}
ProducerImpl中还有对孤儿事务(如发送事务消息中,客户端党机,此时Broker还存留半事务未结束)的处理,该方法是 RocketMQ 客户端中用于处理 孤儿事务消息恢复 的核心逻辑,主要在服务端检测到未决事务(未提交/回滚的事务)时被调用,触发客户端对事务状态的检查和最终处理。
@Override
public void onRecoverOrphanedTransactionCommand(Endpoints endpoints, RecoverOrphanedTransactionCommand command) {
// 从 RecoverOrphanedTransactionCommand 命令中提取 transactionId (事务ID)和 messageId (消息ID),用于标识需要处理的事务消息。
final String transactionId = command.getTransactionId();
final String messageId = command.getMessage().getSystemProperties().getMessageId();
// 检查事务检查器 :
// 若 checker (事务检查器,由业务方实现)未注册( null == checker ),直接记录错误日志并返回,避免后续无效操作。
if (null == checker) {
log.error("No transaction checker registered, ignore it, messageId={}, transactionId={}, endpoints={},"
+ " clientId={}", messageId, transactionId, endpoints, clientId);
return;
}
MessageViewImpl messageView;
try {
// 将服务端传递的 Protobuf 格式消息解码为客户端可识别的 MessageViewImpl 对象。若解码失败(捕获 Throwable ),记录错误日志并终止流程。
messageView = MessageViewImpl.fromProtobuf(command.getMessage());
} catch (Throwable t) {
log.error("[Bug] Failed to decode message during orphaned transaction message recovery, messageId={}, "
+ "transactionId={}, endpoints={}, clientId={}", messageId, transactionId, endpoints, clientId, t);
return;
}
ListenableFuture<TransactionResolution> future;
try {
// 通过 ListenableFuture 实现事务检查的异步执行,避免阻塞主线程,提升客户端处理性能。
// - 使用 ListeningExecutorService 包装线程池 telemetryCommandExecutor ,提交一个 Callable 任务,调用 checker.check(messageView) 执行具体的事务状态检查逻辑(由业务方实现,返回 TransactionResolution 表示事务最终决议)。
final ListeningExecutorService service = MoreExecutors.listeningDecorator(telemetryCommandExecutor);
final Callable<TransactionResolution> task = () -> checker.check(messageView);
future = service.submit(task);
} catch (Throwable t) {
// - 若提交任务失败(如线程池拒绝),创建一个 SettableFuture 并设置异常,确保后续回调能捕获错误。
final SettableFuture<TransactionResolution> future0 = SettableFuture.create();
future0.setException(t);
future = future0;
}
Futures.addCallback(future, new FutureCallback<TransactionResolution>() {
@Override
public void onSuccess(TransactionResolution resolution) {
try {
if (null == resolution || TransactionResolution.UNKNOWN.equals(resolution)) {
return;
}
// 若事务决议 resolution 非 UNKNOWN ,则调用 endTransaction 方法向服务端反馈最终事务状态(提交/回滚),完成事务消息的最终处理。
final GeneralMessage generalMessage = new General

最低0.47元/天 解锁文章
894





