微服务框架支持

news2024/9/28 11:15:19

事务上下文

  • 目录
    • 概述
      • 需求:
    • 设计思路
    • 实现思路分析
      • 1.Seata 的事务上下文由 RootContext 来管理。
      • 2.应用可以通过 RootContext 的 API 接口来获取当前运行时的全局事务 XID。
      • 3.应用是否运行在一个全局事务的上下文中,就是通过 RootContext 是否绑定 XID 来判定的。
      • 4.事务传播
  • 参考资料和推荐阅读

Survive by day and develop by night.
talk for import biz , show your perfect code,full busy,skip hardness,make a better result,wait for change,challenge Survive.
happy for hardess to solve denpendies.

目录

在这里插入图片描述

概述

Seata 的事务上下文由 RootContext 来管理。

需求:

Seata 的事务上下文由 RootContext 来管理。

设计思路

应用开启一个全局事务后,RootContext 会自动绑定该事务的 XID,事务结束(提交或回滚完成),RootContext 会自动解绑 XID。

实现思路分析

1.Seata 的事务上下文由 RootContext 来管理。

// 绑定 XID
RootContext.bind(xid);

// 解绑 XID
String xid = RootContext.unbind();

2.应用可以通过 RootContext 的 API 接口来获取当前运行时的全局事务 XID。

// 获取 XID
String xid = RootContext.getXID();

3.应用是否运行在一个全局事务的上下文中,就是通过 RootContext 是否绑定 XID 来判定的。

public static boolean inGlobalTransaction() {
return CONTEXT_HOLDER.get(KEY_XID) != null;
}

4.事务传播

  1. 服务内部的事务传播

默认的,RootContext 的实现是基于 ThreadLocal 的,即 XID 绑定在当前线程上下文中。

  1. 服务内部的事务传播
    默认的,RootContext 的实现是基于 ThreadLocal 的,即 XID 绑定在当前线程上下文中。
public class ThreadLocalContextCore implements ContextCore {

    private ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal<Map<String, String>>() {
        @Override
        protected Map<String, String> initialValue() {
            return new HashMap<String, String>();
        }

    };

    @Override
    public String put(String key, String value) {
        return threadLocal.get().put(key, value);
    }

    @Override
    public String get(String key) {
        return threadLocal.get().get(key);
    }

    @Override
    public String remove(String key) {
        return threadLocal.get().remove(key);
    }
}

所以服务内部的 XID 传播通常是天然的通过同一个线程的调用链路串连起来的。默认不做任何处理,事务的上下文就是传播下去的。

如果希望挂起事务上下文,则需要通过 RootContext 提供的 API 来实现:

// 挂起(暂停)
String xid = RootContext.unbind();

// TODO: 运行在全局事务外的业务逻辑

// 恢复全局事务上下文
RootContext.bind(xid);

  1. 跨服务调用的事务传播
    通过上述基本原理,我们可以很容易理解:
    跨服务调用场景下的事务传播,本质上就是要把 XID 通过服务调用传递到服务提供方,并绑定到 RootContext 中去。
    只要能做到这点,理论上 Seata 可以支持任意的微服务框架。

对 Dubbo 支持的解读:
下面,我们通过内置的对 Dubbo RPC 支持机制的解读,来说明 Seata 在实现对一个特定微服务框架支持的机制。

对 Dubbo 的支持,我们利用了 Dubbo 框架的 org.apache.dubbo.rpc.Filter 机制。

/**
 * The type Transaction propagation filter.
 */
@Activate(group = { Constants.PROVIDER, Constants.CONSUMER }, order = 100)
public class TransactionPropagationFilter implements Filter {

    private static final Logger LOGGER = LoggerFactory.getLogger(TransactionPropagationFilter.class);

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String xid = RootContext.getXID(); // 获取当前事务 XID
        String rpcXid = RpcContext.getContext().getAttachment(RootContext.KEY_XID); // 获取 RPC 调用传递过来的 XID
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("xid in RootContext[" + xid + "] xid in RpcContext[" + rpcXid + "]");
        }
        boolean bind = false;
        if (xid != null) { // Consumer:把 XID 置入 RPC 的 attachment 中
            RpcContext.getContext().setAttachment(RootContext.KEY_XID, xid);
        } else {
            if (rpcXid != null) { // Provider:把 RPC 调用传递来的 XID 绑定到当前运行时
                RootContext.bind(rpcXid);
                bind = true;
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("bind[" + rpcXid + "] to RootContext");
                }
            }
        }
        try {
            return invoker.invoke(invocation); // 业务方法的调用

        } finally {
            if (bind) { // Provider:调用完成后,对 XID 的清理
                String unbindXid = RootContext.unbind();
                if (LOGGER.isDebugEnabled()) {
                    LOGGER.debug("unbind[" + unbindXid + "] from RootContext");
                }
                if (!rpcXid.equalsIgnoreCase(unbindXid)) {
                    LOGGER.warn("xid in change during RPC from " + rpcXid + " to " + unbindXid);
                    if (unbindXid != null) { // 调用过程有新的事务上下文开启,则不能清除
                        RootContext.bind(unbindXid);
                        LOGGER.warn("bind [" + unbindXid + "] back to RootContext");
                    }
                }
            }
        }
    }
}

参考资料和推荐阅读

  1. https://seata.io/zh-cn/docs/user/microservice.html

欢迎阅读,各位老铁,如果对你有帮助,点个赞加个关注呗!~

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习--房屋销售的探索性数据分析

目录 一、导入相关包 二、读取数据 三、做简单的处理 总结 一、导入相关包 numpy&#xff1a;python中做数据分析常用的包&#xff1b; pandas&#xff1a;也是用于数据分析&#xff0c;擅长处理表&#xff0c;数据没那么大要放入内存中&#xff0c;这将是首选&#xff1…

client-go源码学习(二):Reflector、DeltaFIFO

本文基于Kubernetes v1.22.4版本进行源码学习&#xff0c;对应的client-go版本为v0.22.4 3、Informer机制 在Kubernetes系统中&#xff0c;组件之间通过HTTP协议进行通信&#xff0c;在不依赖任何中间件的情况下需要保证消息的实时性、可靠性、顺序性等。那么Kubernetes是如何…

重装操作系统win10+重装sqlserver+数据库可视化工具

sqlserver安装以及使用 一、重装操作系统 操作系统win10镜像 原因&#xff1a;sqlserver无数次失败让我放弃原来操作系统。 重装操作系统三步骤 1>下载大白菜一键装机工具 2>有一个u盘&#xff0c;8G以上存储空间 3>win10系统镜像 详细讲解&#xff1a; win10系统镜…

管道和重定向

1.重定向 1.输出重定向 > 一般用于在控制台上为了避免看到过多冗余的代码代码操作&#xff0c;所以将正确和错误的结果信息写到文件夹中 标准输出 1> 1>> [rootiZ2zef4rb5ixg6sieztgsdZ /]# cat /etc/passwd > file.txt //将/etc/passwd中输出的结果打印…

ElasticSearch6.x版本概念介绍及Kibana操作的增删改查常用API

文章目录一、概念介绍1.接近实时(NRT Near Real Time )2.索引(index)3.类型(type)4.映射(mapping)5.文档(document)6.概念关系图二、Kibana的基本操作1.创建dangdang索引并创建product类型2.删除dangdang索引3.创建id为1的文档记录4.查询id为1的文档记录5.删除id为1的文档记录6…

【2022年终总结】:小伙子还需努力呀~

文章目录前言第一次遇见CSDN我的收获我的迷茫我的展望前言 有一段时间没写博客了&#xff0c;具体什么原因呢&#xff1f;先买个关子&#xff0c;埋在下面的文字里。 眨眼时间&#xff0c;在CSDN待了快一年了&#xff0c;这一年的时间里有收获有感动&#xff0c;当然&#xff0…

IO多路复用【学习笔记】

1.用户空间和内核空间 虚拟内存被操作系统划分成两块&#xff1a;内核空间和用户空间&#xff0c;内核空间是内核代码运行的地方&#xff0c;用户空间是用户程序代码运行的地方。当进程运行在内核空间时就处于内核态&#xff0c;当进程运行在用户空间时就处于用户态。 为了安全…

elasticsearch在linux环境安装使用过程遇到的问题

es在linux环境安装遇到问题 1、启动失败日志 ERROR: [1] bootstrap checks failed [1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be con…

MCU-51:单片机之AT24C02学习

目录一、存储器介绍1.1 RAM1.2 ROM二、AT24C022.1 AT24C02介绍2.2 引脚及应用电路2.3 内部结构框图三、I2C总线3.1 I2C总线介绍3.2 I2C电路规范3.3 I2C时序结构3.4 I2C数据帧3.5 AT24C02数据帧四、代码演示4.1 AT24C02数据存储4.2 秒表(定时器扫描按键数码管)注意&#xff1a;一…

ECG信号处理——包括基本波检测、信号去噪、信号重建度量(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 心电图&#xff08;ECG&#xff09;信号自动分析与诊断是目前信号处理领域中的研究热点之一,其真正实现将有力地促进医疗事业的…

集合引用类型——对象

介绍&#xff1a; 依据变量分类&#xff1a;ECMAScript变量包括两种不同类型的值&#xff1a;原始值和引用值。 依据类型分类&#xff1a;ECMAScript类型包括两种不同类型的值&#xff1a;基本数据类型和集合数据类型。 原始值和引用值&#xff1a; 原始值就是最简单的数据&am…

网络层IP

文章目录网络层基本概念IP报头分片和组装如何分片如何组合16位标识符13位片偏移3位标志网段划分IP地址的分类CIDRIP地址数量限制私有IP和公网IP运营商路由网络层 http和tcp只考虑了两端的问题&#xff0c;并没有考虑路途中的事情。路由查找 IP的构成&#xff1a;32位网络号主…

【Ctfer训练计划】——(八)

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门 创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座…

fx5u 脉冲输出指令PLSY(DPLSY)4种写法

本文描述三菱FX5U的 脉冲输出指令PLSY(DPLSY)&#xff0c;4种写法&#xff0c;都有效。 第一行&#xff1a;设置脉冲输出频率 第二行&#xff1a;DPLSY D0 K0 K1,FX5U &#xff0c;第二个参数是脉冲数量&#xff0c;设置为K0表示一值输出脉冲。 第三个参数是轴号K1,表示Y0脉冲…

2023跨年倒计时2023最炫烟花秀烟花代码

&#x1f4cb; 前言 &#x1f5b1; 博客主页&#xff1a;在下马农的碎碎念✍ 本文由在下马农原创&#xff0c;首发于CSDN&#x1f4c6; 首发时间&#xff1a;2022/12/30&#x1f4c5; 最近更新时间&#xff1a;2022/12/30&#x1f935; 此马非凡马&#xff0c;房星本是星。向前…

c#入门-补码

补码 明明我们用正数用的更多&#xff0c;如果把0归到负数里面&#xff0c;那么正数就是整的2n次方了。 为什么不这么做呢&#xff1f; 如果你的手表快了20分钟&#xff0c;你可以&#xff1a; 1.把他调慢20分钟 2.再调快11小时40分钟 其实负数就是一个特别大的正数。CPU没有…

Unity 基于法线和深度实现完美描边,可独立控制物体描边

目录前言自定义PostProcessOutlineShader关键代码说明1 使用深度绘制描边1.1 获得斜四方形UV坐标&#xff1a;1.2 采样四方向深度2 使用法线绘制描边3 解决倾斜表面白块问题3.1 计算视方向3.2 使用视方向修正阈值4 单独控制物体是否显示描边OutlineShader完整代码前言 最近项目…

github上传代码(亲测实用)

又被github上传代码折腾了我3个小时&#xff0c;各种问题都遇到过&#xff0c;最后写篇博客记录一下&#xff0c;方便后续上传。 github创建项目完成后&#xff0c;就会出现上传指令&#xff0c;如下图所示&#xff1a; 现在只需要按着命令的提示一步步执行&#xff1b; 1.点…

一文读懂HTTPS

大家第一次接触 HTTPS 协议的时候是不是和我一样&#xff0c;非常困惑。 这玩意概念又多又繁琐。尤其是里面的公钥私钥啥的。 当时就特别想知道&#xff0c;为什么用公钥加密却不能用公钥解密&#xff1f; 看完这篇文章你会弄明白&#xff0c;同时还会解锁很多HTTPS里的细节…

ansible的安装

自定义环境 1.操作环境 角色主机名IP地址组名 控制主机 server.example.com 192.168.90.134 server 受控主机 node1.example.com 192.168.90.135 node1 受控主机 node2.example.com 192.168.90.133 node2 需要保准三台主机能够互相通信。设置同一种网络模式&#xff0…