Seata 配置中心实现原理

Seata 可以支持多个第三方配置中心,那么 Seata 是如何同时兼容那么多个配置中心的呢?下面我给大家详细介绍下 Seata 配置中心的实现原理。

配置中心属性加载

在 Seata 配置中心,有两个默认的配置文件:

file.conf 是默认的配置属性,registry.conf 主要存储第三方注册中心与配置中心的信息,主要有两大块:

registry {
  # file 、nacos 、eureka、redis、zk、consul、etcd3、sofa
  # ...
}

config {
  # file、nacos 、apollo、zk、consul、etcd3
  type = "file"
  nacos {
    serverAddr = "localhost"
    namespace = ""
  }
  file {
    name = "file.conf"
  }
  # ...
}

其中 registry 为注册中心的配置属性,这里先不讲,config 为配置中心的属性值,默认为 file 类型,即会加载本地的 file.conf 里面的属性,如果 type 为其它类型,那么会从第三方配置中心加载配置属性值。

在 config 模块的 core 目录中,有个配置工厂类 ConfigurationFactory,它的结构如下:

可以看到都是一些配置的静态常量:

REGISTRY_CONF_PREFIX、REGISTRY_CONF_SUFFIX:配置文件名、默认配置文件类型;

SYSTEM_PROPERTY_SEATA_CONFIG_NAME、ENV_SEATA_CONFIG_NAME、ENV_SYSTEM_KEY、ENV_PROPERTY_KEY:自定义文件名配置变量,也说明我们可以自定义配置中心的属性文件。

ConfigurationFactory 里面有一处静态代码块,如下:

io.seata.config.ConfigurationFactory

根据自定义文件名配置变量找出配置文件名称与类型,如果没有配置,默认使用 registry.conf,FileConfiguration 是 Seata 默认的配置实现类,如果为默认值,则会更具 registry.conf 配置文件生成 FileConfiguration 默认配置对象,这里也可以利用 SPI 机制支持第三方扩展配置实现,具体实现是继承 ExtConfigurationProvider 接口,在META-INF/services/创建一个文件并填写实现类的全路径名,如下所示:

第三方配置中心实现类加载

在静态代码块逻辑加载完配置中心属性之后,Seata 是如何选择配置中心并获取配置中心的属性值的呢?

我们刚刚也说了 FileConfiguration 是 Seata 的默认配置实现类,它继承了 AbstractConfiguration,它的基类为 Configuration,提供了获取参数值的方法:

short getShort(String dataId, int defaultValue, long timeoutMills);
int getInt(String dataId, int defaultValue, long timeoutMills);
long getLong(String dataId, long defaultValue, long timeoutMills);
// ....

那么意味着只需要第三方配置中心实现该接口,就可以整合到 Seata 配置中心了,下面我拿 zk 来做例子:

首先,第三方配置中心需要实现一个 Provider 类:

实现的 provider 方法如其名,主要是输出具体的 Configuration 实现类。

那么我们是如何获取根据配置去获取对应的第三方配置中心实现类呢?

在 Seata 项目中,获取一个第三方配置中心实现类通常是这么做的:

Configuration CONFIG = ConfigurationFactory.getInstance();

在 getInstance() 方法中主要是使用了单例模式构造配置实现类,它的构造具体实现如下:

io.seata.config.ConfigurationFactory#buildConfiguration:

首先从 ConfigurationFactory 中的静态代码块根据 registry.conf 创建的 CURRENT_FILE_INSTANCE 中获取当前环境使用的配置中心,默认为为 File 类型,我们也可以在 registry.conf 配置其它第三方配置中心,这里也是利用了 SPI 机制去加载第三方配置中心的实现类,具体实现如下:

如上,即是刚刚我所说的 ZookeeperConfigurationProvider 配置实现输出类,我们再来看看这行代码:

EnhancedServiceLoader.load(ConfigurationProvider.class,Objects.requireNonNull(configType).name()).provide();

EnhancedServiceLoader 是 Seata SPI 实现核心类,这行代码会加载 META-INF/services/META-INF/seata/目录中文件填写的类名,那么如果其中有多个配置中心实现类都被加载了怎么办呢?

我们注意到 ZookeeperConfigurationProvider 类的上面有一个注解:

@LoadLevel(name = "ZK", order = 1)

在加载多个配置中心实现类时,会根据 order 进行排序:

io.seata.common.loader.EnhancedServiceLoader#findAllExtensionClass:

io.seata.common.loader.EnhancedServiceLoader#loadFile:

这样,就不会产生冲突了。

但是我们发现 Seata 还可以用这个方法进行选择,Seata 在调用 load 方法时,还传了一个参数:

Objects.requireNonNull(configType).name()

ConfigType 为配置中心类型,是个枚举类:

public enum ConfigType {
  File, ZK, Nacos, Apollo, Consul, Etcd3, SpringCloudConfig, Custom;
}

我们注意到,LoadLevel 注解上还有一个 name 属性,在进行筛选实现类时,Seata 还做了这个操作:

根据当前 configType 来判断是否等于 LoadLevel 的 name 属性,如果相等,那么就是当前配置的第三方配置中心实现类。

第三方配置中心实现类

ZookeeperConfiguration 继承了 AbstractConfiguration,它的构造方法如下:

构造方法创建了一个 zkClient 对象,这里的 FILE_CONFIG 是什么呢?

private static final Configuration FILE_CONFIG = ConfigurationFactory.CURRENT_FILE_INSTANCE;

原来就是刚刚静态代码块中创建的 registry.conf 配置实现类,从该配置实现类拿到第三方配置中心的相关属性,构造第三方配置中心客户端,然后实现 Configuration 接口时:

就可以利用客户端相关方法去第三方配置获取对应的参数值了。

第三方配置中心配置同步脚本

上周末才写好,已经提交 PR 上去了,还处于 review 中,预估会在 Seata 1.0 版本提供给大家使用,敬请期待。

具体位置在 Seata 项目的 script 目录中:

config.txt 为本地配置好的值,搭建好第三方配置中心之后,运行脚本会将 config.txt 的配置同步到第三方配置中心。

更多精彩文章请关注作者维护的公众号「后端进阶」,这是一个专注后端相关技术的公众号。
关注公众号并回复「后端」免费领取后端相关电子书籍。
欢迎分享,转载请保留出处。

原文地址:https://www.cnblogs.com/objcoding/p/12051212.html

时间: 2024-08-01 15:35:05

Seata 配置中心实现原理的相关文章

微服务架构:动态配置中心搭建

版权声明:本文为博主原创文章,转载请注明出处,欢迎交流学习! 在微服务架构中,服务之间有着错综复杂的依赖关系,每个服务都有自己的依赖配置,在运行期间很多配置会根据访问流量等因素进行调整,传统的配置信息处理方式是将配置信息写入xml..properties等配置文件中,和应用一起打包,每次修改配置信息,都需要重新进行打包,效率极低,动态配置中心就是为了解决这一问题.动态配置中心也是一个微服务,我们把微服务中需要动态配置的配置文件存放在远程git私有仓库上,微服务会去服务器读取配置信息,当我们在本地

SpringCloud之配置中心Config

commons 工程commons 工程 - POM 文件<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://mav

微服务统一配置中心原理

为什么微服务要统一配置中心? 1:传统直接在properties里配置会导致任何人都能看到商户密钥,任何员工都可以利用这个密钥白嫖公司的,而且我们也不知道是谁在白嫖; 2:接口升级变更了,传统的写法需要在每个properties里修改,会很麻烦; 3:公司的一些通用配置也需要在每个project里配,重复且不利于修改; 解决:用zookeeper 原文地址:https://www.cnblogs.com/mlzdev/p/11317984.html

#研发解决方案介绍#基于持久化配置中心的业务降级

郑昀 最后更新于2014/4/18 关键词:业务降级,配置中心,基本可用性, A.业务降级的背景知识: 淘宝就双十一课题曾经讲过: 『 所谓业务降级,就是牺牲非核心的业务功能,保证核心功能的稳定运行.简单来说,要实现优雅的业务降级,需要将功能实现拆分到相对独立的不同代码单元,分优先级进行隔离.在后台通过开关控制,降级部分非主流程的业务功能,减轻系统依赖和性能损耗,从而提升集群的整体吞吐率. 』 主动关闭系统功能的场景: 我们更新系统或数据库刷库时,可能会提出,某天凌晨几点到几点不能下单,几点到几

开源全局配置中心XDiamond

项目地址: https://github.com/hengyunabc/xdiamond 简介 全局配置中心,存储应用的配置项,解决配置混乱分散的问题.名字来源于淘宝的开源项目diamond,前面加上一个字母X以示区别. wiki 设计思路 在线演示 地址:xdiamond.coding.io,登陆选择standard,用户名密码:admin/admin 特性 所见即所得,在管理界面上看到的所有配置即项目运行时的配置 支持groupId,artifactId,version,profile四个维

Apollo配置中心介绍

1.What is Apollo 1.1 背景 随着程序功能的日益复杂,程序的配置日益增多:各种功能的开关.参数的配置.服务器的地址-- 对程序配置的期望值也越来越高:配置修改后实时生效,灰度发布,分环境.分集群管理配置,完善的权限.审核机制-- 在这样的大环境下,传统的通过配置文件.数据库等方式已经越来越无法满足开发人员对配置管理的需求. Apollo配置中心应运而生! 1.2 Apollo简介 Apollo(阿波罗)是携程框架部门研发的开源配置管理中心,能够集中化管理应用不同环境.不同集群的

Spring Cloud(Dalston.SR5)--Config 集群配置中心

Spring Cloud Config 是一个全新的项目,用来为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,他分为服务端和客户端两个部分.服务端也称为分布式配置中心,是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息.加密.解密信息等访问接口:而客户端则是为微服务架构中的各个微服务应用,通过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息.服务端与客户端的结构图如下: ? ? ? ? Spring Cloud 程序在进行

spring cloud 入门系列七:基于Git存储的分布式配置中心--Spring Cloud Config

我们前面接触到的spring cloud组件都是基于Netflix的组件进行实现的,这次我们来看下spring cloud 团队自己创建的一个全新项目:Spring Cloud Config.它用来为分布式系统中的基础设施和微服务提供集中化的外部配置支持,分为服务端和客户端两个部分. 其中服务端也称为分布式配置中心,他是独立的微服务应用,用来连接配置仓库并为客户端提供获取接口(这些接口返回配置信息.加密.解密信息等): 客户端是微服务架构中的各个微服务应用或基础设施,它们通过制定的配置中心来管理

如何借助配置中心ACM加速企业IT服务快速迭代

摘要: 在5月29日召开的第二届研发效能嘉年华中,云效邀请了阿里云产品团队的伏羿和来自阿里巴巴中间件技术部的彦林带来了"如何借助配置中心ACM加速企业IT服务快速迭代"的主题分享. 分别对配置中心ACM和ACM技术进行了讲解,并且对ACM的主要应用场景进行了介绍,并进行了Demo环节. 在5月29日召开的第二届研发效能嘉年华中,云效邀请了阿里云产品团队的伏羿和来自阿里巴巴中间件技术部的彦林带来了"如何借助配置中心ACM加速企业IT服务快速迭代"的主题分享. 分别对配