Seata 动态配置订阅与降级实现原理

简介: Seata 的动态降级需要结合配置中心的动态配置订阅功能。动态配置订阅,即通过配置中心监听订阅,根据需要读取已更新的缓存值,ZK、Apollo、Nacos 等第三方配置中心都有现成的监听器可实现动态刷新配置;动态降级,即通过动态更新指定配置参数值,使得 Seata 能够在运行过程中动态控制全局事务失效(目前只有 AT 模式有这个功能)。那么 Seata 支持的多个配置中心是如何适配不同的动态配置订阅以及如何实现降级的呢?下面从源码的层面详细给大家讲解一番。

Seata 的动态降级需要结合配置中心的动态配置订阅功能。动态配置订阅,即通过配置中心监听订阅,根据需要读取已更新的缓存值,ZK、Apollo、Nacos 等第三方配置中心都有现成的监听器可实现动态刷新配置;动态降级,即通过动态更新指定配置参数值,使得 Seata 能够在运行过程中动态控制全局事务失效(目前只有 AT 模式有这个功能)。


那么 Seata 支持的多个配置中心是如何适配不同的动态配置订阅以及如何实现降级的呢?下面从源码的层面详细给大家讲解一番。


动态配置订阅



Seata 配置中心有一个监听器基准接口,它主要有一个抽象方法和 default 方法,如下:


io.seata.config.ConfigurationChangeListener

640.png

该监听器基准接口主要有两个实现类型:


  1. 实现注册配置订阅事件监听器:用于实现各种功能的动态配置订阅,比如 GlobalTransactionalInterceptor 实现了 ConfigurationChangeListener,根据动态配置订阅实现的动态降级功能;
  2. 实现配置中心动态订阅功能与适配:对于目前还没有动态订阅功能的 file 类型默认配置中心,可以实现该基准接口来实现动态配置订阅功能;对于阻塞订阅需要另起一个线程去执行,这时候可以实现该基准接口进行适配,还可以复用该基准接口的线程池;以及还有异步订阅,有订阅单个 key,有订阅多个 key 等等,我们都可以实现该基准接口以适配各个配置中心。


这里就用默认的 file 配置中心,以它的实现类 FileListener 举例子,它的实现逻辑如下:

640.jpg


如上,


  • dataId:为订阅的配置属性;
  • listener:配置订阅事件监听器,用于将外部传入的 listener 作为一个 wrapper,执行真正的变更逻辑,这里特别需要注意的是,该监听器与 FileListener 同样实现了 ConfigurationChangeListener 接口,只不过 FileListener 是用于给 file 提供动态配置订阅功能,而 listener 用于执行配置订阅事件
  • executor:用于处理配置变更逻辑的线程池,在 ConfigurationChangeListener#onProcessEvent 方法中用到。


FileListener#onChangeEvent 方法的实现让 file 具备了动态配置订阅的功能,它的逻辑如下:


无限循环获取订阅的配置属性当前的值,从缓存中获取旧的值,判断是否有变更,如果有变更就执行外部传入 listener 的逻辑。


ConfigurationChangeEvent 用于保存配置变更的事件类,它的成员属性如下:

640.png

这里的 getConfig 方法是如何感知 file 配置的变更呢?我们点进去,发现它最终的逻辑如下:

640.png

发现它是创建一个 future 类,然后包装成一个 Runnable 放入线程池中异步执行,最后调用 get 方法阻塞获取值,那么我们继续往下看:

640.png

allowDynamicRefresh:动态刷新配置开关;

targetFileLastModified:file 最后更改的时间缓存。


以上逻辑:


获取 file 最后更新的时间值 tempLastModified,然后对比对比缓存值 targetFileLastModified,如果 tempLastModified > targetFileLastModified,说明期间配置有更改过,这时就重新加载 file 实例,替换掉旧的 fileConfig,使得后面的操作能够获取到最新的配置值。


添加一个配置属性监听器的逻辑如下:

640.png


configListenersMap 为 FileConfiguration 的配置监听器缓存,它的数据结构如下:

ConcurrentMap<String/*dataId*/, Set<ConfigurationChangeListener>> configListenersMap


从数据结构上可看出,每个配置属性可关联多个事件监听器。

最终执行 onProcessEvent 方法,这个是监听器基准接口里面的 default 方法,它会调

用 onChangeEvent 方法,即最终会调用 FileListener 中的实现。


动态降级



有了以上的动态配置订阅功能,我们只需要实现 ConfigurationChangeListener 监听器,就可以做各种功能,目前 Seata 只有动态降级有用到动态配置订阅的功能。

在「Seata AT 模式启动源码分析」这篇文章中讲到,Spring 集成 Seata 的项目中,在 AT 模式启动时,会用 用GlobalTransactionalInterceptor 代替了被 GlobalTransactional 和 GlobalLock 注解的方法,GlobalTransactionalInterceptor 实现了 MethodInterceptor,最终会执行 invoker 方法,那么想要实现动态降级,就可以在这里做手脚。


  • 在 GlobalTransactionalInterceptor 中加入一个成员变量:
private  volatile  boolean disable;


在构造函数中进行初始化赋值:

640.png

ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION(service.disableGlobalTransaction)这个参数目前有两个功能:


  1. 在启动时决定是否开启全局事务;
  2. 在开启全局事务后,决定是否降级。


  • 实现 ConfigurationChangeListener:

85e4d375b029de2c93a1e516dd6e9d42.png

这里的逻辑简单,就是判断监听事件是否属于 ConfigurationKeys.DISABLE_GLOBAL_TRANSACTION 配置属性,如果是,直接更新 disable 值。


  • 接下来在 GlobalTransactionalInterceptor#invoke 中做点手脚

ffb667c29ab326212b7a77c1f589b3df.png


如上,disable = true 时,不执行全局事务与全局锁。


  • 配置中心订阅降级监听器

io.seata.spring.annotation.GlobalTransactionScanner#wrapIfNecessary

85e7f78b3bf11dae51573a094033381c.png

在 Spring AOP 进行 wrap 逻辑过程中,当前配置中心将订阅降级事件监听器。


相关文章
|
4天前
|
自然语言处理 监控 Dubbo
Seata常见问题之使用tcc模式配置yml如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
83 4
|
10月前
|
SpringCloudAlibaba NoSQL Java
Seata配置参考
SeataClient是直接集成到我们的业务微服务中,SeataClient的原理是代理我们jdbc数据源,在应用程序和数据库之间加了一层,通过添加的这一层来做事务管理。
366 0
|
4天前
|
SQL 关系型数据库 MySQL
【Seata1.5.2 下载 & 配置 & 整合 & 踩坑 & 测试】—— 含各种踩坑记录(详细版)(上)
【Seata1.5.2 下载 & 配置 & 整合 & 踩坑 & 测试】—— 含各种踩坑记录(详细版)
234 0
|
4天前
|
存储 关系型数据库 MySQL
Seata常见问题之程序读的nocas的配置如何解决
Seata 是一个开源的分布式事务解决方案,旨在提供高效且简单的事务协调机制,以解决微服务架构下跨服务调用(分布式场景)的一致性问题。以下是Seata常见问题的一个合集
55 0
|
4天前
|
Shell 测试技术 Linux
单节点Seata支持多环境配置隔离,允许你独立配置不同环境的参数。
单节点Seata支持多环境配置隔离,允许你独立配置不同环境的参数。
38 1
|
4天前
|
中间件 关系型数据库 MySQL
Windows 安装 Seata 1.6.1 并配置开机自启
Windows 安装 Seata 1.6.1 并配置开机自启
|
4天前
|
SQL Java 数据库
【Seata1.5.2 下载 & 配置 & 整合 & 踩坑 & 测试】—— 含各种踩坑记录(详细版)(下)
【Seata1.5.2 下载 & 配置 & 整合 & 踩坑 & 测试】—— 含各种踩坑记录(详细版)(下)
115 0
|
8月前
|
弹性计算 Java Nacos
Spring Cloud Alibaba Seata 配置
Spring Cloud Alibaba Seata 配置
|
12月前
|
SQL JSON 搜索推荐
SEATA相关概念以及实现原理
SEATA相关概念以及实现原理
94 0
|
12月前
|
SQL Java 关系型数据库
SEATA1.6.1的配置与使用
SEATA1.6.1的配置与使用
2061 0

热门文章

最新文章