RocketMQ源码解析之消息生产者(事务消息源码篇)

1. 一张图回顾事务消息的原理

在这里插入图片描述
(图片可能不太清楚,可以访问我画的原图:process on 地址 ,方便的话给点个赞!谢谢)
我们在《RocketMQ源码解析之消息生产者(事务消息原理篇)》一文中详细介绍了RocketMQ的事务消息执行流程与原理。
这里文字再描述下这个流程,首先是我们生产者端先向broker发送事务消息,这个broker 收到事务消息之后,然后将这个消息存储到系统的一个topic里面就是RMQ_SYS_TRANS_HALF_TOPIC, 然后封装响应结果给消息发送者,需要注意的是这个一来一回 发送的是同步消息,然后 这个消息生产者收到sendResult,也就是收到这个响应后判断状态,如果是ok的,就执行本地事务,这个本地事务就是你自己写的那个 listener的executeLocalTransaction 方法,如果你本地事务执行成功,并且commit,这个时候你就返回一个commit 告诉broker我要提交这个事务,如果你本地事务执行失败,然后本地事务回滚,也需要告诉broker回滚这个消息。
这里需要注意2个点,一个是因为是同步发送,发送消息的线程与执行本地事务的线程是一个;第二个是告诉broker 提交事务,这个是个单向发送。 如果broker 收到你的本地事务执行状态,就会执行相应的操作,如果是commit,就将 在RMQ_SYS_TRANS_HALF_TOPIC 的消息取出来,转成原来的那个消息(为什么要转?因为当初发送消息需要将topic,queue id 转成 half topic 的,这样的话才能存到 RMQ_SYS_TRANS_HALF_TOPIC这个topic里面),然后将消息写到你一开始那个topic里面,写入成功之后(此时你的消息消费者就能消费着它了), 封装一个删除标识的消息,然后放到RMQ_SYS_TRANS_OP_HALF_TOPIC 这个topic 里面,这是commit的逻辑,如果你要rollback的话,就是找到写到RMQ_SYS_TRANS_HALF_TOPIC 这个topic的消息,然后封装一个删除标识的消息,放到RMQ_SYS_TRANS_OP_HALF_TOPIC 这个topic里面去。
上面这都是正常情况,接着说说异常情况:
(1)如果一开始发送的事务消息没有收到呢?
这个时候就会超时或者其他异常,你就不会再执行这个本地事务
(2)broker 收到这个事务消息,并且存放到了half topic里面,然后再给你响应的时候由于网络波动或者其他原因,没有发送到消息生产者 这边,然后消息生产者这边也会进行重试,有个一个成功的就行了,然后就会调用本地事务执行,如果没有成功的话就异常了,本地事务没法触发执行
(3)告诉broker 本地事务状态的时候网络波动,或者服务挂了,怎么办?
这个时候其实broker 有个后台线程会隔一段时间就扫描那些没有确认或者回滚的消息,会调用消息生产者这边的checkLocalTransaction 检查本地事务的方法,这就需要你在执行本地事务编程的时候,将这个 消息事务id与本地事务状态记录下来,以备检查使用。默认broker回询问你15次,15后没结果直接把这个消息扔了。

2.源码解析

先来看下发送事务消息的流程:
在这里插入图片描述
检查listener ,就是咱们编程需要实现的那个listener,里面有执行本地事务,然后检查本地事务的方法。我们接着来看看sendMessageInTransaction方法:
在这里插入图片描述
这里是发送同步消息的方法,整个流程就跟发送同步消息一样的,我们这里就不赘述了。
接着就是broker 响应回来sendResult,看看往下是怎么处理的(注意,这个还是在sendMessageInTransaction 方法里)
在这里插入图片描述
其实这一段代码就是执行本地事务,然后标记 本地事务状态,接着往下:
在这里插入图片描述
我们需要注意下这个endTransaction是单向发送,我们来看看它干了啥
在这里插入图片描述
这个方法其实就是封装了一下结束事务的请求头,然后调用了 endTranscationOneway发送消息。
在这里插入图片描述
可以看出来使用的是单向发送。
好了到这我们正常流程就结束了,但是还有一些异常流程,然后broker 就需要发送检查本地事务的消息给我们消息生产者
这个我们需要从收到请求入手,然后它的请求code 就是CHECK_TRANSACTION_STATE
在这里插入图片描述
收到检查本地事务请求会交给 checkTransactionState 方法来执行
在这里插入图片描述
这个方法首先是根据group找到对应的 producer,然后交给producer的checkTransactionState 方法来处理
先来看下这个方法的最后一句
在这里插入图片描述
交给check线程池,这个check线程池也是需要你自己指定的,然后这个request其实就是这一行上面那一大堆代码
在这里插入图片描述
我们只是截取了一部分,其实就是找到咱们那个listener ,然后执行checkLocalTransaction 的方法。
最后是交给了processTransactionState 方法来处理这个结果
在这里插入图片描述
这个方法也是很简单,其实就是封装这个结束事务的请求头,判断一下这个事务执行状态,封装不同的类型,然后交由给 endTransactionOneway 方法进行发送,这个发送其实就是上面我们说的那个单向发送。

3.总结

首先是再次介绍了一下RocketMQ的事务消息原理,其实很简单,分成两个阶段,第一个阶段就是prepare,将消息先发送到broker的half topic,这个时候消息消费者是消费不到的,然后告诉消息生产者执行本地事务,本地事务执行状态提交给broker ,然后broker根据状态进行提交或者回滚,提交之后 消费者就能消费着了,如果没有将本地事务状态提交给broker 或者遇到 网络问题,服务挂了的问题,broker会有个线程来不断询问消息生产者 本地事务的执行结果,这个过程一个消息最多15次,超过后就会扔掉这个消息,之后我们又解析了一下发送事务消息的源码与 接收检查本地事务请求的源码实现。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页