快来学习对微服务进行集中式配置管理的重要机制-服务配置中心吧

2022-10-28 15:05:33 浏览数 (1)

服务配置中心

服务配置中心是对微服务进行集中式配置管理的重要机制。集中配置管理可以分离应用代码与不同环境下的配置信息,实现应用“一次打包、随处运行”,通过这种外部化的配置管理还可以实现配置修改实时生效、灵活的权限及安全管理等特性。

服务配置中心管理

在传统的中心化单体架构中,所有的配置项都是通过本地的静态配置文件进行管理的,对于不同的环境(开发、测试、生产),我们需要手动维护和切换调整不同的配置。在分布式微服务环境下,一个系统往往又由多个微服务组成(X个),每个微服务都需要独立的配置文件(Y个),而分布式部署又会有多个机器或者容器(Z个),那么在这种情况下,如果使用静态配置管理,我们需要同时管理X×Y×Z个配置文件,这样无疑是非常低效并且容易出错的。

所以我们需要将各种配置参数全部放到一个集中的地方(服务配置中心,简称配置中心)进行统一管理,并提供一套标准的接口规范。当不同服务需要获取参数时,可以从配置中心拉取和配置,当修改配置时,可以由配置中心统一下发给集群中的所有实例。配置中心可以解决传统的配置文件的如下问题:

● 服务修改不灵活。配置中心具备“实时更新”的功能,它可以用来解决传统的服务修改不灵活问题。当线上系统需要调整参数的时候,只需要在配置中心动态修改即可。

● 配置文件无法区分环境。通过“配置与应用分离”可以解决传统的配置文件无法区分环境问题,配置并不跟着环境走,当不同环境有不同需求的时候,就到配置中心获取,可降低运维成本。

● 配置文件过于分散。采用“配置集中管理”可解决传统的配置文件过于分散的问题。所有的配置都集中在配置中心管理,不需要每个项目都自带一个配置文件,降低了开发成本。

● 配置修改无法追溯。采用静态配置文件,当配置进行修改后,不容易形成记录,更无法追溯是谁修改的、什么时间修改的、修改前的内容是什么。当配置出错时,更没办法回滚。

配置中心可以统一记录所有更改记录,用于后续审计管理。

配置中心的核心能力

如下图所示是配置中心的核心能力。

● 交付与配置分离:在打包部署时,传统应用系统会为不同环境打出不同配置包,例如为开发、测试、生产环境分别制作发布包,每个包里包含特定配置。现代微服务提倡云原生( Cloud Native ) 和 不 可 变 基 础 设 施 ( ImmutableInfrastructure)的理念,推荐采用容器镜像这种方式打包和交付微服务,应用镜像一般只打一个包,可以部署到不同环境。这就要求交付物(比如容器镜像)和配置分离,交付件只制作一份,并且是不可变的,可以部署到任意环境,而配置由配置中心集中管理,所有环境的配置都可以在配置中心集中配置,运行期应用根据自身环境到配置中心动态拉取相应的配置。

● 抽象标准化:企业应该由框架或者中间件团队提供标准化的配置中心服务,封装配置管理的细节和配置的不同格式,方便用户进行自助式的配置管理。一般用户只需要关注两个抽象和标准化的接口:

○ 配置管理界面UI,方便应用开发人员管理和发布配置。

○ 封装好的客户端API,方便应用集成和获取配置。

● 多环境多集群:现代微服务应用大都采用多环境部署,一般标准化的环境有开发、测试、生产等,有些应用还需要多集群部署,例如支持跨机房或者多版本部署。配置中心需要支持对多环境和多集群应用配置的集中式管理。

● 高可用:配置中心必须保证高可用,否则可能影响大量微服务的正常启动或者配置更新。在极端的情况下,如果配置中心不可用,客户端也需要有降级策略,保证应用不受影响。

● 实时性:配置更新需要尽快通知到客户端,这个周期不能太长,理想状态下应该是实时的。有些配置的实时性要求很高,例如主备切换配置或者蓝绿部署配置,需要具有秒级切换配置的能力。

● 治理:配置中心需要具有治理能力,具体包括:可进行人员登录操作记录追溯;提供配置版本控制,出现问题时能够及时回滚到上一个版本;提供配置权限控制,发布配置变更需要认证授权,不是所有人都能修改和发布配置;支持灰度发布,发布配置时可以先让少数实例生效,确保没有问题再逐步放量。

配置中心的其他优势

● 实现实时的配置读取、更新、取消。

● 权限控制,能够根据公司的SSO或者LDAP基础设施进行配置权限管理。

● 环境管理,开发、测试、生产环境下的配置可以做隔离处理。

● 配置回滚,当发现配置错误或者在该配置下程序发生异常时可以立即回滚到之前的版本。

● 灰度发布,有时候我们新上线一个功能,想先通过少部分流量测试一下,我们可以随机只修改部分应用的配置,测试正常后再将功能推送到所有的应用。

Spring Cloud Config

Spring Cloud Config为分布式系统配置提供了服务端和客户端的支持,包括Config Server和Config Client两部分。Spring CloudConfig通过配置服务(Config Server)来为所有的环境和应用提供外部配置的集中管理,它适用于各类Spring应用,也能对应用的开发、测试、生产环境的配置做切换、迁移。

使用Spring Cloud Config Server,你可以在所有环境中管理应用程序的外部属性,还可以分离应用与配置文件,并且根据应用当前所处环境,动态地加载对应的配置文件,它符合“应用配置与代码隔离”的原则。Spring Cloud Config的主要特性

● 提供服务端和客户端支持。

● 集中式、中心化管理分布式环境下的应用配置。

● 使用Git管理方式,天然具备版本控制能力。

● 基于Spring环境,实现了与Spring应用的无缝集成。

● 支持动态更新配置文件。

● 语言独立,可用于任何语言开发的程序。

● 默认基于Git仓库实现(也支持SVN、数据库、MongoDB),可进行配置的版本管理。

Spring Cloud Config基本原理

Config Server是一个可横向扩展、集中式的配置服务器,它用于集中管理应用程序各个环境下的配置,默认使用Git存储配置内容(也可使用SVN、本地文件系统或Vault存储配置),因此可以实现对配置的版本控制与内容审计。如下图所示是Config Server的架构图。

● Config Client(Client A、Client B、Client C):提供了基于Spring的客户端,应用只要在代码中引入Config Client的jar包即可工作。

● Config Server:需要独立部署的一个Web应用,它负责把Git上的配置返回客户端。

● Remote Git repository:即远程Git仓库,我们会把配置信息存储在一个远程仓库中,通过现成的Git客户端来管理配置。

● Local Git repository:即Config Server的本地Git仓库,Config Server接到来自客户端的配置获取请求后,先把远程仓库的配置克隆到本地的临时目录,然后从临时目录读取配置并返回。

Spring Cloud Config的使用

Spring Cloud Config基于HTTP,通过统一的配置服务中心进行集中化的远程配置文件管理。Config Client可以通过指定配置中心服务地址,主动从配置中心拉取服务的配置信息,完成配置获取,从而达到配置与代码分离的效果。

Spring Cloud Config默认使用Git的存储和管理方式,在采用Config作为生产和测试环境配置中心管理配置文件时,首选的存储方案也是使用Git。使用Git的主要优势如下:

● 它天然支持对配置文件的版本管理。

● Git默认提供Web界面的管理方式,方便用户从GitLab前端查看配置和管理配置,同时可以利用Git的权限管理给不同用户赋予不同的查看配置文件的权限。

● Git引擎还具备WebHook功能,它可以实现配置文件的动态更新等。

● 支持使用SVN、文件服务器、JDBC等方式获取配置文件。

Spring Cloud Config客户端加载流程

客户端从配置管理中获取配置的执行流程如下:

( 1 ) 应 用 启 动 时 根 据 bootstrap.yml 中 配 置 的 应 用 名{application} 、 环 境 名 {profile} 、 分 支 名 {label} , 向 ConfigServer请求获取配置信息。

(2)Config Server根据Config Client的请求及配置从Git仓库中查找并定位符合的配置文件。

(3)Config Server通过“git clone”命令将配置下载到Git本地文件系统,并建立缓存。

(4)Config Server创建Spring的ApplicationContext实例从Git本地仓库中加载配置文件,然后将读取的配置信息返回给ConfigClient。

(5)Config Client在获取到Config Server返回的配置数据后,将配置内容加载到客户端自己的ApplicationContext实例,该配置内容的优先级高于客户端内部的配置内容。

下 面 我 们 结 合 实 例 讲 解 一 下 基 本 的 Config Server 和 ConfigClient的接入步骤。

Config Server接入步骤

在启动配置Config Server前,如果使用Git仓库存储配置文件,则需要先搭建Git仓库,篇幅所限,Git仓库搭建步骤省略。

1.引入Config Server Maven依赖

2.启动配置中心服务,让客户端可以发现服务端,在启动类上加注解@EnableConfigServer

3.添加配置中心配置文件

● spring.cloud.config.server.git.uri :配 置 的 Git 仓 库 地址。

● spring.cloud.config.server.git.searchPaths:与URI配合使用,定位Git库的子目录,指定搜索路径,如果有多个路径则使用“,”分隔。

● spring.cloud.config.server.git.basedir:使用Git作为后端配置,需要从远程库获取配置文件,存储到本地文件。默认存储在系统临时目录下,目录名的前缀为config-repo-,如在Linux下可能是/tmp/config-repo-。因为/tmp下的内容有可能被误删,为了保险,最好修改存储目录。如果要修改存储目录,可以修改spring.cloud.config.server.git.basedir参数。

● spring.cloud.config.server.git.force-pull:配置中心从远程Git仓库读取数据时,可能会出现本地的文件拷贝被污染的情况,这时配置中心无法从远程库更新本地配置。设置force-pull=true,可强制从远程库中更新本地库。

● spring.cloud.config.server.git.username:访问Git仓库的用户名。

● spring.cloud.config.server.git.password:访问Git仓库的用户密码。

4.引入Security配置

Config Server如果希望客户端能够授权访问配置中心,需要引入Maven依赖:

加入如下配置文件:

客户端需要增加如下配置来授权访问配置中心服务器:

下面看一下Config定义好的配置文件资源与URI的映射规则:

需要注意的是:

● URI中的application对应是Config Client的应用名称,如果在Git中是用应用名来定义目录的,这个应用也对应你在Git中的目录名称。

● URI中的profile对应的是应用激活使用的环境名称,如果在Maven中指定Profile,可以在Maven中指定配置中通过标签<activation>指定Profile,也可以从配置文件中指定,一般Profile有test、dev、prod等。

● URI中label指的是Git的分支,默认是master分支。

5.测试验证

上述配置设置好后,可以启动Config Server,通过HTTP网络工具测试是否可以取得Config Server的配置信息。使用下面的地址访问配置中心:

配置中心会返回如下响应:

Config Client接入步骤

1.引入客户端依赖

注意:Maven依赖中需要加入对Actuator的支持,以实现ConfigClient中用一个refresh端点来实现配置文件的刷新功能。另外,在Config Client的配置文件中也需要打开相关Actuator端点的配置生效功能。

2.添加Config Client配置文件

● 上述配置文件中的uri对应配置中心的Server地址,label代表请求的是哪个Git分支,profile对应分支下的配置文件,如test、dev、prod。考虑到Spring Boot对配置文件的加载优先级,最好在bootstrap.yml文件里命名配置文件,因为加载远程配置文件的优先级会比加载本地配置文件高。

● spring.profile.active可以指定Spring Boot运行的环境,而 spring.cloud.config.profile是客户端指定拉取资源库的

profile,如果有多个profile,一般最后一个起作用。

● 如果我们希望在启动一个服务时若无法连接到服务端,能够快速返回失败信息,则可以通过failFast来设置开启ConfigClient快速失效功能。

● management:endpoints:web:exposure:include:“*”表示打开全部请求端点,要让Config Client支持动态刷新和查看配置端点信息,只需要打开部分端点。

3.启动Config Client类

Config Client获取分布式配置信息主要有下面两种方式。

● 使用@Value方式获取配置文件

这种方式是获取配置文件的常用方式,最简单,代码如下:

● 通过创建一个远程配置信息Bean的方式获取配置信息首 先 定 义 一 个 映 射 远 程 配 置 信 息 的 Bean 类RemoteConfigProperties,该类中所有的属性名均需与配置中心的配置文件的内容相同,例如demo-config-profile-env,字段名为demoConfigProfileEnv,如果属性中有点,则应视点后面的部分为下级,应再定义相关的配置映射类,该类的完整代码如下:

注意:属性字段名与配置项的名称应保持一致,若有下级则定义下级的配置类,需要根据配置类采用Java的内部类进行映射匹配。例如,配置文件如果是Map或List接口,则需要使用Java的对应数据接口存储映射配置文件。

Config Server配置详解

上一节我们介绍了基本的配置中心接入步骤。对于公司内使用的配置中心(Config Server),如果考虑同时支持不同部门的不同项目,需要考虑更多的Config Server管理Git的配置使用方式。

Spring Cloud Config中的占位符

Spring Cloud Config服务器支持一个Git仓库URI,其中包含{application}、{profile}及{label}的占位符,使用Git URI的占位符可以轻松支持“每个应用程序一个repo”的策略。当使用Git作为配置中心来存储各个微服务应用的配置文件时,URI中的占位符的使用可以帮助我们规划和实现通用的仓库配置,代码示例如下:

说明:这里的{application}代表了应用名称,当客户端向Config Server发起获取配置请求时,Config Server会根据客户端的spring.application.name信息来填充{application}占位符以定位配置资源的存储位置。基于一个环境一个仓库的使用原则,可以使用{profile}代替{application}。另外在{application}中使用特殊字符"(_)"可以支持多组织。

说明:这 里 的 {application} 的 格 式 为 “organization ( _ )application”。 注意:{label}很特别,如果Git分支和标签包含“/”,那么{label}在HTTP的URL中应用使用“(_)”替代,以避免改变URI的含义,指向其他URI资源。例如,如果标签是foo/bar,则替换“/”将导致出现类似于foo(_)bar的标签。如果使用像curl这样的命令行客户端(例如使用引号将其从Shell中转出来),请小心URL中的方括号。

多模式匹配及多存储仓库

我们也可以使用{application}/{profile}进行模式匹配,以便获取 相 应 的 配 置 文 件 。它 的 格 式 是 用 一 组 逗 号 分 隔 的{application}/{profile},其中的参数可以使用通配符。目前,我们加入了一个应用客户端,它的配置如下:

Config Client按照上述配置请求服务器仓库地址,下面我们通过模式配置规则对Config Server服务端进行HTTP请求,地址为uri:

http://locahost: 6001/test-config-client/dev/master。

由URI可知,我们使用了/{application}/{profile}[/{label}的匹配模式。下面我们看一下加入了多模式匹配的配置中心(ConfigServer)的Config配置:

上面的配置分别对应三组不同配置匹配规则,默认情况下,Git访问 的 是 https://localhost/spring-cloud-samples/config-repo 仓 库地址。如果你的URI中的{application}/{profile}没有匹配到Git默认的仓库地址,Config Server将根据模式匹配规则尝试能否匹配其他仓库地址:

● “simple”仓库匹配的是“simple/*”(在所有环境下它仅仅匹配一个仓库simple),目前从我们的客户端请求URI中发现,这项repo资源不匹配。

● “local” 仓 库 将 匹 配 所 有 名 字 以 “local” 开 头 的{application},也是在所有的环境下。“/*”前缀会自动添加到所有没有设置{profile}的模式中。

● “customize”和“special”使用模式匹配规则,pattern为“customize-*” 标 识 的 应 用 , 表 示 {application} 是 以customize-开头的应用repo资源,例如,customize-configclient的应用名称与customize-*的模式相互匹配,所以返回该资源下的repo资源。

注意:

● 如果模式中需要配置多个值,那么可以使用逗号分隔。

● 如果{application}/{profile}没有匹配到任何资源,则使用配置的默认URI: spring.cloud.config.server.git.uri。

● 当我们使用YAML类型的文件进行配置时,如果模式属性是一个YAML数组,也可以使用YAML数组格式来定义。这样可以设置成多个配置文件,如下代码所示:

路径搜索占位符等配置

当我们把配置文件存放在Git仓库的子目录中时,可以通过设置searchPaths来指定该目录。同样,searchPaths也支持上面的占位符,示例如下:

说 明 :在 上 面 的 例 子 中 , 将 在 demo-config-repo 和 以springCloud-config开头的目录中搜索配置文件。cloneOnStart设置为True时,服务器在启动的时候克隆仓库,而如果没有该项配置,表示服务器可以在第一次请求配置文件时克隆远程仓库。

Config Server定制化开发

Config Server配置中心默认提供Git的方式及Git文件管理GUI作为配置中心的前端可视化管理工具,但是默认的Git文件存储方式存在配置文件的配置项格式校验、不同项目的版本回滚及配置实时更新等问题,所以我们可以通过对Config Server进行二次开发实现定制化的功能。

Config Server源码解析

● Config Server自动化配置

查 看 @EnableConfigServer 注 解 , 通 常 都 是 引 入 某 种Configuration类来达到自动化装配某些Bean的目的,如下代码所示:

● ConfigServerConfiguration实现了一个标志类

ConfigServerConfiguration类里面并没有实现太多Bean的装配,这里利用一种折中方式引入需要的自动配置。请看下面的类,Marker唯一被引用的地方在类中。

说明:

@ConditionalOnBean( ConfigServerConfiguration.Marker.class)表示当装配了ConfigServerConfiguration.Marker的实例时才会执行ConfigServerAutoConfiguration。

从源码我们可以发现,Config配置类中另外引入了5个辅助配置类,篇幅所限这里不对每个配置类进行详细说明,仅对对ConfigServer最为关键的 EnvironmentRepositoryConfiguration加以说明。

● 查看 EnvironmentRepositoryConfiguration类

这里的@Import又引入了7种配置类,查看文档会发现其实刚好对应 Config Server 的 几 种 实 现 方 式 , 其 中 Git 使 用 的 配 置 类 就 是 GitRepositoryConfiguration。

以 GitRepositoryConfiguration为例,GitRepositoryConfiguration 其 实 是 默 认 的 实 现 方 式 , 查 看DefaultRepositoryConfiguration的代码:

它首先装配一个 MultipleJGitEnvironmentRepository的Bean对象,然而实际每种配置类的最终实现都会装配EnvironmentRepository配置类。最终通过调用EnvironmentRepository的findOne方法来查询配置。而接口EnvironmentRepository(Config Server实现定制化加载 配 置 的 关 键 接 口 ) 只 提 供 了 一 个 方 法 findOne , 通 过 传 入application、profile和label来获得配置项:

配置中心定制化实现

在默认情况下,Config Server可以通过在配置文件中进行简单配置实现数据库访问和存储。但是,Config Server自带的SQL实现方式存在一定的缺陷,因为它的表结构的功能定义相对简单,没有版本管理和权限管理功能。下面我们基于Config Server开源实现,根据“读写分离”的原则实现自定义的配置中心定制化改造。

● 配置文件写入部分在开始实现自定义的EnvironmentRepository之前,我们需要进行数据库表设计,因为篇幅所限,我们仅列出几个核心表的设计。在设计时主要使用表config_namespace存储配置文件主表 , 包 含 所 有 应 用 及 对 应 配 置 文 件 信 息 ,`application_name`、`label`和`profile`三个字段是联合主键,对应一个应用配置文件。表结构如下:

对于配置文件的更改历史和版本相关信息,我们使用表config_release 表 示 , 其 中 namespace_id 对 应config_namespace 中 `application_name` 、 `label` 和`profile`联合主键的信息。下面是表的结构:

在 自 定 义 的 Config Server 中 , 我 们 需 要 使 用 注 解@EnableConfigServer初始化并加载配置中心的环境变量以启动配置中心,代码如下:

根据上述数据库表结构设计,配置文件写入部分我们主要提供一个Admin管理端,允许前端通过GUI界面实现对配置文件在数据库中的插入、修改、删除,这里我们仅介绍核心表的添加配置功能,主要通过Controller类、Service类与DAO类实现数据库插入配置项,配置服务中心的Controller类负责配置文件的添加,实现代码实例如下:

配置服务中心的Service类的配置文件插入实现代码如下:

配 置 服 务 中 心 DAO 类 的 配 置 文 件 写 入 使 用 Spring Boot 的@Repository注解及MyBatis实现,代码如下:

对应的MyBatis配置如下:

● 配置文件读取部分如上述分析,可以使用EnvironmentRepository作为我们实现自定义的配置文件存储查询的接口类,只需要覆盖实现自定义的EnvironmentRepository的Bean,就可以替换读取逻辑,从默认的基于Git的存储读取方式转换为我们想要的基于数据库的配置读取方式。定制化EnvironmentRepository的主要代码如下:

○ 说明1#:使用JDBC的方式将初始化定制化。

○ 说明2#:findOne是EnvironmentRepository的接口,源码如下:

该方法中最核心的机制就是通过application、profile、label三个参数找到对应的配置文件信息(基本单元)。

在默认的Config Server实现方式中,它使用Git Client完成Git文件读取的方式加载对应Git Server中的配置文件,而在我们的定制化实现方式中,使用JDBC的方式获取配置文件信息。说明2#根据上述三个参数查找出三个联合主键对应的唯一配置文件ID。

○ 说明3#:这部分代码通过上一步取得的唯一ID信息从配置表(config_release)中取得配置文件信息,该信息对应ConfigRelease类模型信息。下面是ConfigRelease的代码实现:

EnvironmentController实现配置中心Admin前端管理及权限验证入口,Config Server使用HTTP的方式作为ConfigClient 配 置 文 件 的 接 口 调 用 方 式 , 所 以 我 们 通 过EnvironmentController来暴露给客户端的配置入口,代码如下:

可以看出,/{name}/{profiles}/{label:.*}路径参数正好与我们 的 请 求 方 式 相 对 应 , 因 此 Config Server 是 通 过 建 立 一 个RestController 来 接 收 读 取 配 置 请 求 的 , 然 后 使 用EnvironmentRepository来进行配置查询,返回Environment对象的JSON结果值,客户端接收时也应该将其反序列化为Environment的一个实例。

本文给大家讲解的内容对微服务进行集中式配置管理的重要机制——服务配置中心

  1. 下篇文章给大家讲解的内容是微服务网关:微服务网关模式
  2. 觉得文章不错的朋友可以转发此文关注小编;
  3. 感谢大家的支持!

本文就是愿天堂没有BUG给大家分享的内容,大家有收获的话可以分享下,想学习更多的话可以到微信公众号里找我,我等你哦。

0 人点赞