Seata AT TM->RC->RM一次完整的交互过程

原理

TM两阶段:

阶段1:TM向TC申请全局事务,netty客户端发起了一次记录xid的请求

阶段2:TC协调之后,决定执行RM是否提交或者回滚。

spring公共组件部分

1、SeataAutoConfiguration类

利用springboot自动装配机制从spring.factories文件加载自动配置类SeataAutoConfiguration

org.springframework.boot.autoconfigure.EnableAutoConfiguration=io.seata.spring.boot.autoconfigure.SeataAutoConfiguration@ConditionalOnProperty(prefix = SEATA_PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
@AutoConfigureAfter({SeataCoreAutoConfiguration.class})
public class SeataAutoConfiguration {private static final Logger LOGGER = LoggerFactory.getLogger(SeataAutoConfiguration.class);@Bean(BEAN_NAME_FAILURE_HANDLER)@ConditionalOnMissingBean(FailureHandler.class)public FailureHandler failureHandler() {return new DefaultFailureHandlerImpl();}@Bean@DependsOn({BEAN_NAME_SPRING_APPLICATION_CONTEXT_PROVIDER, BEAN_NAME_FAILURE_HANDLER})@ConditionalOnMissingBean(GlobalTransactionScanner.class)public GlobalTransactionScanner globalTransactionScanner(SeataProperties seataProperties, FailureHandler failureHandler,ConfigurableListableBeanFactory beanFactory,@Autowired(required = false) List<ScannerChecker> scannerCheckers) {if (LOGGER.isInfoEnabled()) {LOGGER.info("Automatically configure Seata");}// set bean factoryGlobalTransactionScanner.setBeanFactory(beanFactory);// add checkers// '/META-INF/services/io.seata.spring.annotation.ScannerChecker'GlobalTransactionScanner.addScannerCheckers(EnhancedServiceLoader.loadAll(ScannerChecker.class));// spring beansGlobalTransactionScanner.addScannerCheckers(scannerCheckers);// add scannable packagesGlobalTransactionScanner.addScannablePackages(seataProperties.getScanPackages());// add excludeBeanNamesGlobalTransactionScanner.addScannerExcludeBeanNames(seataProperties.getExcludesForScanning());// create global transaction scannerreturn new GlobalTransactionScanner(seataProperties.getApplicationId(), seataProperties.getTxServiceGroup(), failureHandler);}
}

2、 GlobalTransactionScanner类

public class GlobalTransactionScanner extends AbstractAutoProxyCreatorimplements ConfigurationChangeListener, InitializingBean, ApplicationContextAware, DisposableBean

初始化TM、RM的netty客户端,提供aop能力

2-1、初始化TM、RM的netty客户端

io.seata.spring.annotation.GlobalTransactionScanner#afterPropertiesSet

spring-bean初始化赋值回调,这里初始化TM、RM的netty客户端,为后续发起请求做准备。

    @Overridepublic void afterPropertiesSet() {if (disableGlobalTransaction) {if (LOGGER.isInfoEnabled()) {LOGGER.info("Global transaction is disabled.");}ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,(ConfigurationChangeListener)this);return;}if (initialized.compareAndSet(false, true)) {initClient();}}private void initClient() {if (LOGGER.isInfoEnabled()) {LOGGER.info("Initializing Global Transaction Clients ... ");}if (StringUtils.isNullOrEmpty(applicationId) || StringUtils.isNullOrEmpty(txServiceGroup)) {throw new IllegalArgumentException(String.format("applicationId: %s, txServiceGroup: %s", applicationId, txServiceGroup));}//init TMTMClient.init(applicationId, txServiceGroup, accessKey, secretKey);if (LOGGER.isInfoEnabled()) {LOGGER.info("Transaction Manager Client is initialized. applicationId[{}] txServiceGroup[{}]", applicationId, txServiceGroup);}//init RMRMClient.init(applicationId, txServiceGroup);if (LOGGER.isInfoEnabled()) {LOGGER.info("Resource Manager is initialized. applicationId[{}] txServiceGroup[{}]", applicationId, txServiceGroup);}if (LOGGER.isInfoEnabled()) {LOGGER.info("Global Transaction Clients are initialized. ");}registerSpringShutdownHook();}

2-2、aop代理实现

io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary,递归调用适配代理,Seata重写了这个方法,TCC代理、AT代理使用的还是spring那一套代理区分方式(jdk还是cglib)

    /*** The following will be scanned, and added corresponding interceptor:** TM:* @see io.seata.spring.annotation.GlobalTransactional // TM annotation* Corresponding interceptor:* @see io.seata.spring.annotation.GlobalTransactionalInterceptor#handleGlobalTransaction(MethodInvocation, AspectTransactional) // TM handler** GlobalLock:* @see io.seata.spring.annotation.GlobalLock // GlobalLock annotation* Corresponding interceptor:* @see io.seata.spring.annotation.GlobalTransactionalInterceptor#handleGlobalLock(MethodInvocation, GlobalLock)  // GlobalLock handler** TCC mode:* @see io.seata.rm.tcc.api.LocalTCC // TCC annotation on interface* @see io.seata.rm.tcc.api.TwoPhaseBusinessAction // TCC annotation on try method* @see io.seata.rm.tcc.remoting.RemotingParser // Remote TCC service parser* Corresponding interceptor:* @see io.seata.spring.tcc.TccActionInterceptor // the interceptor of TCC mode*/@Overrideprotected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {// do checkersif (!doCheckers(bean, beanName)) {return bean;}try {synchronized (PROXYED_SET) {if (PROXYED_SET.contains(beanName)) {return bean;}interceptor = null;//check TCC proxyif (TCCBeanParserUtils.isTccAutoProxy(bean, beanName, applicationContext)) {// init tcc fence clean task if enable useTccFenceTCCBeanParserUtils.initTccFenceCleanTask(TCCBeanParserUtils.getRemotingDesc(beanName), applicationContext);//TCC interceptor, proxy bean of sofa:reference/dubbo:reference, and LocalTCCinterceptor = new TccActionInterceptor(TCCBeanParserUtils.getRemotingDesc(beanName));ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,(ConfigurationChangeListener)interceptor);} else {Class<?> serviceInterface = SpringProxyUtils.findTargetClass(bean);Class<?>[] interfacesIfJdk = SpringProxyUtils.findInterfaces(bean);if (!existsAnnotation(new Class[]{serviceInterface})&& !existsAnnotation(interfacesIfJdk)) {return bean;}if (globalTransactionalInterceptor == null) {globalTransactionalInterceptor = new GlobalTransactionalInterceptor(failureHandlerHook);ConfigurationCache.addConfigListener(ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION,(ConfigurationChangeListener)globalTransactionalInterceptor);}interceptor = globalTransactionalInterceptor;}LOGGER.info("Bean[{}] with name [{}] would use interceptor [{}]", bean.getClass().getName(), beanName, interceptor.getClass().getName());if (!AopUtils.isAopProxy(bean)) {bean = super.wrapIfNecessary(bean, beanName, cacheKey);} else {AdvisedSupport advised = SpringProxyUtils.getAdvisedSupport(bean);Advisor[] advisor = buildAdvisors(beanName, getAdvicesAndAdvisorsForBean(null, null, null));int pos;for (Advisor avr : advisor) {// Find the position based on the advisor's order, and add to advisors by pospos = findAddSeataAdvisorPosition(advised, avr);advised.addAdvisor(pos, avr);}}PROXYED_SET.add(beanName);return bean;}} catch (Exception exx) {throw new RuntimeException(exx);}}

3、GlobalTransactionalInterceptor类

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/310853.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML---利用CSS3制作网页动画

文章目录 目录 文章目录 本章目标 一.CSS3概述 CSS函数概述 二.CSS3变形 transform属性 translate()&#xff1a;平移函数 scale()&#xff1a;缩放函数 rotate()&#xff1a;旋转函数 skew()&#xff1a;倾斜函数 三.CSS3过渡 四.CSS动画 练习 旋转按钮 本章目标 会使用…

Spark作业的调度与执行流程

Apache Spark是一个分布式计算框架&#xff0c;用于处理大规模数据。了解Spark作业的调度与执行流程是构建高效分布式应用程序的关键。本文将深入探讨Spark作业的组成部分、调度过程以及执行流程&#xff0c;并提供丰富的示例代码来帮助大家更好地理解这些概念。 Spark作业的组…

utf8mb4_0900_ai_ci、utf8mb4_0900_as_ci、utf8mb4_0900_as_cs 这三者有什么区别

utf8mb4_0900_ai_ci, utf8mb4_0900_as_ci, 和 utf8mb4_0900_as_cs 是 MySQL 数据库中使用的字符集和校对规则。这些校对规则决定了如何比较和排序字符数据。它们属于 utf8mb4 字符集&#xff0c;这是 UTF-8 编码的超集&#xff0c;支持最多 4 个字节的字符&#xff0c;能够存储…

MySQL多表查询的方法(含例子)

我们查两张及以上表的时候&#xff0c;普通的查询语法(select * from 表名&#xff09;不能发挥作用。下面我演示两张表和三张表的查询方法。 前提&#xff1a; 如图存在三张表a&#xff0c;b&#xff0c;c&#xff1a;a表是学生基础信息&#xff0c;b表是教师学科信息&#…

校园外卖趋势洞察与未来预测系统

校园外卖趋势洞察与未来预测系统 项目概述数据集技术栈功能特点创新点实施步骤 项目概述 本项目旨在打造一套基于Flask和Echarts的校园外卖趋势洞察与未来预测系统。通过深度分析模拟校园外卖数据集&#xff0c;结合机器学习算法&#xff0c;我们致力于提供对学生外卖点餐规律…

【基础】【Python网络爬虫】【3.chrome 开发者工具】(详细笔记)

Python网络爬虫基础 chrome 开发者工具元素面板&#xff08;Elements)控制台面板&#xff08;Console&#xff09;资源面板&#xff08;Source&#xff09;网络面板&#xff08;Network&#xff09;工具栏Requests Table详情 chrome 开发者工具 ​ 当我们爬取不同的网站是&…

Android studio 多界面的跳转和返回

一、新建一个Empty Activity项目&#xff1a; 二、修改activity_main.xml布局文件&#xff1a; <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android"http://schemas.android.com/a…

unity控制摄像机几种视角实现方式

目录 1、按下鼠标右键可以实现摄像机上下左右旋转 2、自由视角 3、摄像头跟随视角 4、跟随自由视角 5、第一人称跟随视角 python学习汇总连接&#xff1a; 1、按下鼠标右键可以实现摄像机上下左右旋转 这段代码定义了一个名为CameraRotate的脚本&#xff0c;用于控制摄像…

【Python特征工程系列】教你利用XGBoost模型分析特征重要性(源码)

这是Python特征工程系列原创文章&#xff0c;我的第186篇原创文章。 一、问题 应用背景介绍&#xff1a; 如果有一个包含数十个甚至数百个特征的数据集&#xff0c;每个特征都可能对你的机器学习模型的性能有所贡献。但是并不是所有的特征都是一样的。有些可能是冗余的…

网络安全—认证技术

文章目录 加密认证对称密钥体制公钥密码体制公钥的加密公钥身份认证和加密 鉴别码认证MAC鉴别码 报文摘要认证认证 加密只认证数字签名 通过了解以前前辈们使用的消息认证慢慢渐进到现代的完整的认证体系。所以在学习的时候也很蒙圈&#xff0c;因为前期的很多技术都是有很严重…

数据结构:单调栈

1.单调栈 单调栈是一种数据结构&#xff0c;其中存放的数据应该是有序的&#xff0c;所以单调栈也有单调递减栈和单调递增栈 单调递增栈&#xff1a;栈顶到栈底的元素大小是从小到大 单调递减栈&#xff1a;栈顶到栈底的元素大小是从大到小 单调栈主要就是用来求一个给定序列中…

GenerateBlocks Pro插件 构建更好的WordPress网站

GenerateBlocks Pro插件 构建更好的WordPress网站 GenerateBlocks Pro插件是一个 WordPress 插件&#xff0c;几乎可以完成任何事情&#xff0c;可让您创建轻量级和多功能的网站。由与流行且快速的 GeneratePress 主题相同的创作者构建&#xff0c;该插件不负众望。使用 Genera…