seata客户端执行流程

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 流程图
  • 一、客户端启动
  • 二、GlobalTransactionScanner
    • 1.初始化
    • 2.SeataAutoDataSourceProxyCreator
  • 执行过程
  • 版本对比
  • 总结


流程图

网上找了一张看着还行的流程图
seata客户端执行流程_第1张图片
1、启动客户端
1.1、创建GlobalTransactionScanner对象、初始化TM、初始化RM
1.2、创建SeataAutoDataSourceProxyCreator
2、触发拦截器GlobalTransactionalInterceptor、SeataAutoDataSourceProxyAdvice
2.1、开启全局事务,获取xid并存入本地线程
2.2、注册分支信息,获取branchId
2.3、处理自己业务—这里可能涉及数据源代理的初始化,也可能在其他的数据库操作中已经初始化,记录undo.log日志
2.4、提交本地事务
3、提交全局事务
3.1、成功的话就删除各个服务的undo.log日志
3.2、失败的话,根据xid和branchId查回undo.log日志回滚

一、客户端启动

seata客户端也是一个springboot项目,要接入进来,肯定也是一样的通过SPI机制。那么我们就直接找到spring.factories文件,看到里面就一个SeataAutoConfiguration配置类(注意这里我们公司暂时使用的1.3.0版本)
seata客户端执行流程_第2张图片
在SeataAutoConfiguration类里,我们主要关注两个方法globalTransactionScanner(SeataProperties seataProperties, FailureHandler failureHandler)、seataAutoDataSourceProxyCreator(SeataProperties seataProperties);

二、GlobalTransactionScanner

1.初始化

对于spring相关的类,通常我们首先要看的是这个类继承了哪些类,实现了哪些接口seata客户端执行流程_第3张图片
我们看看,首先继承了AbstractAutoProxyCreator,这个类就是spring aop处理类;而GlobalTransactionScanner重写了wrapIfNecessary方法,那么后期的aop代理就会来到这里处理;InitializingBean接口主要功能就是在bean初始化后的调用问题,实现该类就会在bean生命周期的后期自动执行afterPropertiesSet方法;applicationContextAware将ApplicationContext注入, DisposableBean是bean销毁时的回调方法的提供接口;
在创建GlobalTransactionScanner对象的时候,我们先来到的是afterPropertiesSet方法,在方法里有一个initClient(),进入该方法,整体代码还是很清晰的,初始化TM、初始化RM、registerSpringShutdownHook;
seata客户端执行流程_第4张图片
seata客户端执行流程_第5张图片
到此处GlobalTransactionScanner对象的创建也就完成了。那么重新的wrapIfNecessary什么起作用呢?这个是在我们其他类处理代理的时候调用的,这里最终会创建GlobalTransactionalInterceptor实例;这个类实现了MethodInterceptor,那么在后期就对代理类的方法进行拦截;

2.SeataAutoDataSourceProxyCreator

从类名上可以大概猜出这个类是和数据源代理创建相关的。从类的结构上来看,该类继承自AbstractAutoProxyCreator,和GlobalTransactionScanner一样,但是本类重写的方法是getAdvicesAndAdvisorsForBean方法;这个是后期数据源代理时需要用的;在创建
SeataAutoDataSourceProxyCreator过程中,主要就是创建了一个Advisor;然后该类的入参Advice是SeataAutoDataSourceProxyAdvice,所以在后期的方法拦截中,起作用的是SeataAutoDataSourceProxyAdvice里的invoke方法;
在创建DataSource时,会调用GlobalTransactionScanner的wrapIfNecessary方法,最终生成的对象是DataSourceProxy;那DataSourceProxy的初始化是什么时候完成的呢?1.3.0和1.4版本是不同的。我们先按1.3.0的介绍;

执行过程

当我们执行带有@GlobalTransactional的方法时,首先进入GlobalTransactionalInterceptor的拦截方法获取方法上的注解,如果有全局事务则走全局事务的处理流程,有全局锁的则走全局锁的流程,否则走其他的流程
seata客户端执行流程_第6张图片
我们以全局事务的路线往下走
seata客户端执行流程_第7张图片
来到execute方法我们看看beginTransaction(txInfo, tx);seata客户端执行流程_第8张图片
这里面是一个模板模式设计思路,before和after都可以自己重写的;所以我们看的是begin方法,这个方法主要就是获取xid,并存放在ThreadLocal中
seata客户端执行流程_第9张图片
接下来就是执行自己的业务了,但是在1.3.0的时候这里会多一个操作(首次执行业务,任何需要调用数据库的业务)
rs = business.execute();这里会进入到我们前面说的SeataAutoDataSourceProxyAdvice的拦截方法中seata客户端执行流程_第10张图片
如果是第一次的话,这里会进行DataSourceProxy初始化;seata客户端执行流程_第11张图片
seata客户端执行流程_第12张图片
此致就完成了DataSourceProxy的初始化;后期再调用putDataSource时就会直接获取到第一次创建的;这是1.3.0版本的,后面我们会把1.4.2的版本贴出来做个对比;
在执行业务里,有一个重要的操作就是向seata-service注册分支信息
seata客户端执行流程_第13张图片
seata客户端执行流程_第14张图片
seata客户端执行流程_第15张图片
这里完成了分支注册,返回分支id,这个是后期回滚或删除undo.log的查询条件;
执行完自己业务后,接下来的就是commitTransaction(tx);
seata客户端执行流程_第16张图片
提交了本地处理结果后,各个服务会等待seata-service通知删除undo.log或回滚。

版本对比

前面我们说了1.3.0数据源代理的过程,1.4.2是怎么样的呢?其实更简单一些,下面我们就来看看
在配置类SeataDataSourceAutoConfiguration中创建SeataDataSourceBeanPostProcessor对象,其实现了BeanPostProcessor,所以在bean的生命周期中会回调postProcessAfterInitialization方法,就是这时对DataSourceProxy初始化的。
seata客户端执行流程_第17张图片
seata客户端执行流程_第18张图片
在这里插入图片描述
我们是按AT模式介绍的,所以走这个流程;到了这里后面的就和1.3.0的版本一样了;也就是说,1.3.0是需要我们执行业务操作或查询数据库时才去初始化DataSourceProxy的,而1.4.2是一开始就初始化了;

总结

写得比较乱,主要是记录下自己学习的情况,要是能帮到你很荣幸,要是没有的话,请勿喷,谢谢。大家一起努力学习吧!!!

你可能感兴趣的:(spring,java,spring,boot)