大家好,又见面了,我是你们的朋友全栈君。
目录
注:主要只做理论性的总结与分析,相关实战代码会在后面的博客中和github中逐步增加。
一、配置中心的由来及选择
(一)配置中心由来
(二)配置中心要求具备的功能
(三)配置中心基本流转图和支撑体系分析
(四)多种配置中心的选择与对比方案
二、Spring Cloud Config概述及基本实现方法介绍
三、Spring Cloud Config结合Git实现配置中心方案
(一)Git版基本工作原理(未加Spring Cloud Bus热刷新)
(二)Git多种配置信息讲解
(三)基本的手动刷新和结合Spring Cloud Bus热刷新
四、Spring Cloud Config结合关系型数据库MYSQL实现配置中心方案
(一)基本实现原理
(二)基本要求讲解
五、Spring Cloud Config结合非关系性数据库MongoDB实现配置中心方案
(一)基本实现原理
(二)基本要求讲解
六、Spring Cloud Config使用技能及功能扩展
(一)基本实用技能:本地参数覆盖远程参数
(二)客户端自动刷新实现
(三)客户端回退功能实现
(四)客户端安全认证机制JWT实现
七、Spring Cloud Config实现客户端及服务端高可用方案
(一)客户端高可用原理及方案
(二)服务端高可用原理及方案
八、Spring Cloud Config与Apollo配置使用实现界面化操作
(一)Apollo基本概述及基本功能介绍
(二)Apollo总体架构模块分析
(三)Apollo客户端设计与运行环境介绍
参考书籍、文献和资料:
注:主要只做理论性的总结与分析,相关实战代码会在后面的博客中和github中逐步增加。
一、配置中心的由来及选择
(一)配置中心由来
互联网时代下的分布式系统,应用部署在N台服务器上或在云化环境以多实例呈现,如果一个实例一个实例(或一台服务器一台服务器)进行修改配置和重启,一是维护成本极高,二是不现实,配置中心的思想便应运而生。配置中心用作集中管理不同环境和不同集群配置,以及在修改配置后实时动态推送到应用动态更新。
配置中心管理作为微服务六大实现技术之一,从模型上来分析,包括4大分类、4个核心需求和2个维度分析,在分布式下配置中心在实现上需要满足3大需求:高效获取、实时感知、分布式访问。基本理论在之前博客中已经讲解过,具体见以下博客链接:https://blog.csdn.net/xiaofeng10330111/article/details/85682513。
(二)配置中心要求具备的功能
配置中心应该剧本具备以下基本功能,具体如图:
这里只展示了基本的实现功能,从功能特性、技术路线、可用性和易用性方面还有更多的功能要求,具体可以见(四)以及对应的配置中心实现方案对比。
(三)配置中心基本流转图和支撑体系分析
具体可如图所示:
(四)多种配置中心的选择与对比方案
具体对比分类 | 具体对比项 | 重要程度 | Spring Cloud Config | Netflix Archaius | Ctrip Apollo | DisConf |
---|---|---|---|---|---|---|
功能特性 | 静态配置管理 | 高 | 基于file | 无 | 支持 | 支持 |
动态配置管理 | 高 | 支持 | 支持 | 支持 | 支持 | |
统一管理 | 高 | 无,需要git、数据库等 | 无 | 支持 | 支持 | |
多维度管理 | 中 | 无,需要git、数据库等 | 无 | 支持 | 支持 | |
变更管理 | 高 | 无,需要git、数据库等 | 无 | 无 | 无 | |
本地配置缓存 | 高 | 无 | 无 | 支持 | 支持 | |
配置更新策略 | 中 | 无 | 无 | 无 | 无 | |
配置锁 | 中 | 支持 | 不支持 | 不支持 | 不支持 | |
配置校验 | 中 | 无 | 无 | 无 | 无 | |
配置生效时间 | 高 | 重启生效,手动刷新 | 手动刷新生效 | 实时 | 实时 | |
配置更新推送 | 高 | 需要手动触发 | 需要手动触发 | 支持 | 支持 | |
配置定时拉取 | 高 | 无 | 无 | 支持 | 配置更新目前依赖事件驱动,client重启或server推送操作 | |
用户权限管理 | 中 | 无,需要git、数据库等 | 无 | 支持 | 支持 | |
授权、审核、审计 | 中 | 无,需要git、数据库等 | 无 | 界面直接提供发布历史和回滚按钮 | 操作记录有赖数据库,但无查询接口 | |
配置版本管理 | 高 | git | 无 | 支持 | 无,需要git、数据库等 | |
配置合规检测 | 高 | 不支持 | 不支持 | 支持(还需完善) | ||
实例配置监控 | 高 | 需要结合Spring Admin | 不支持 | 支持 | 支持,可以查看每个配置在哪台机器上加载 | |
灰度发布 | 中 | 不支持 | 不支持 | 支持 | 不支持部分更新 | |
告警通知 | 中 | 不支持 | 不支持 | 支持邮件方式告警 | 支持邮件方式告警 | |
统计报表 | 中 | 不支持 | 不支持 | 不支持 | 不支持 | |
依赖关系 | 高 | 不支持 | 不支持 | 不支持 | 不支持 | |
技术路线 | 支持Spring Boot | 高 | 原生支持 | 低 | 支持 | 与Spring Boot无关 |
支持Spring Config | 高 | 原生支持 | 低 | 支持 | 与Spring Cloud无关 | |
客户端支持 | 低 | java | java | java、.net | java | |
业务系统入侵性 | 高 | 入侵性弱 | 入侵性弱 | 入侵性弱 | 入侵性弱,支持注解和xml | |
可依赖组件 | 高 | |||||
可用性 | 单点故障(SPOF) | 高 | 支持HA部署 | 支持HA部署 | 支持HA部署 | 支持HA部署,高可用由ZK提供 |
多数据中心部署 | 高 | 支持 | 支持 | 支持 | 支持 | |
配置获取性能 | 高 | unkown | unkown | unkown | unkown | |
易用性 | 配置界面 | 中 | 无,需要git、数据库等操作 | 无 | 统一界面 | 统一界面 |
结论:
- 从整体上来看的话,携程的Apollo性能及各方面相对于其他配置中心而言是最好的,因为其支持pring Boot和Spring Config,所以在微服务架构中建议最好采用Apollo来作为配置中心;
- Spring Cloud Config相对Apollo性能与支持没有很全面,但是可以采用一定的开源技术及现有技术进行改善加之原生支持pring Boot和Spring Config,在微服务架构中也是强烈建议采用的方案;
- 其他两种方案在微服务架构中不建议采用,在此不做分析。
我们主要对Spring Cloud Config进行分析和理解,Apollo做辅助分析,关于Apollo的相关知识有时间在进行学习和分享。
二、Spring Cloud Config概述及基本实现方法介绍
Spring Cloud Config是Spring Cloud微服务体系中的配置中心,是一个集中化外部配置的分布式系统,由服务端和客户端组成,其不依赖于注册中心,是一个独立的配置中心,支持多种存储配置信息形式,目前主要有jdbc、value、native、svn、git,其中默认是git。重点讨论功能有如下两个方面:
- 将程序中配置的各种功能开关、参数配置、服务器地址——>修改后实时生效
- 灰度发布、分环境、分集群管理配置———>全面集中化管理
因为采用native方式必然决定了每次配置完相关文件后一定要重启Spring Cloud Config,所以一般我们不会采用此方案,在实际操作中我们主要的实现方案有以下四种:Spring Cloud Config结合Git实现配置中心方案 Spring Cloud Config结合关系型数据库实现配置中心方案 Spring Cloud Config结合非关系型数据库实现配置中心方案 Spring Cloud Config与Apollo配置结合实现界面化配置中心方案。
三、Spring Cloud Config结合Git实现配置中心方案
(一)Git版基本工作原理(未加Spring Cloud Bus热刷新)
配置客户端启动时会向服务器发起请求,服务端接收到客户端的请求后,根据配置的仓库地址将Git上的文件克隆到本地的一个临时目录中,这个目录是一个Git的本地仓库目录,然后服务端再读取本地文件返回给客户端。这样做的好处是,当Git服务器故障或者网络请求异常时,保证服务端仍然可以正常工作。
在实际实现上,服务端需要配置好git的uri地址信息以及search-paths信息,并在对应Git中与之相对应,客户端在bootstrap文件中按照其内容和具体文件名进行配置label、uri、name、profile等消息即可,但是在基本实现上如果修改文件后依旧需要重启来解决此问题,所以需要进行手动刷新或结合Spring Cloud Bus进行热刷新。
(二)Git多种配置信息讲解
关于Git配置信息而言,其主要有以下几种方式:
1.本地仓库
Spring Cloud Config默认使用Git,对Git的配置也最简单,Config Server可用uri、username、password这三个参数就可以读取配置了,通过Git的版本控制可以使Config Server适应特殊的场景。
测试时我们也可以使用本地仓库的方式,使用file://
前缀,那么uri的配置就可以写作
spring:
cloud:
config:
server:
git:
uri: file://${user.home}/config-repo #注意:Windows系统需要使用file:///前缀
# ${user.home}代表当前用户的家目录
2.占位符配置URI
Spring Cloud Config Server支持占位符的使用,支持{application}
、{profile}
、{label}
这些占位符对Git的uri配置,通过占位符使用应用名称来区分应用对应的仓库然后进行使用。这里需要注意仓库名称和仓库下面的配置文件名称一致才可以,因为配置了spring.cloud.config.name默认占位符匹配的是spring.application.name。
spring:
cloud:
config:
server:
git:
uri: https://github.com/hellxz/SpringCloudlearn/config-repo/{application}
#此时spring.application.name的值会填充到这个uri中,从而达到动态获取不同位置的配置
3.匹配并配置多个仓库
Spring Cloud Config Server除了使用{应用名}/{环境名}
来匹配配置仓库外,还支持通过带有通配符的表达式来匹配。
当有多个匹配规则的时候,可以用逗号分隔多个{应用名}/{环境名}
配置规则。以官方文档例子举例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo #默认的仓库
#注意:配置多个仓库时,Config Server 在启动时会直接克隆第一个仓库的配置库,其他配置库只有请求时才会clone到本地
repos:
simple: https://github.com/simple/config-repo
special:
pattern: special*/dev*,*special*/dev*
uri: https://github.com/special/config-repo
local:
pattern: local*
uri: file:/home/configsvc/config-repo
test:
pattern:
- '*/development'
- '*/staging'
uri: https://github.com/development/config-repo
如果{应用名}/{环境名}
不能匹配到仓库,那么就在默认的uri下去查找配置文件。
上边的例子中,
- simple 仓库自动匹配到
simple/*
- special 仓库的pattern,第一个是应用名以special开头,环境名以dev开头;第二个是应用名包含special,环境名以dev开头;多个匹配到同一uri的pattern用逗号分割
- local 仓库的的pattern也会自动补全为
local*/*
- test仓库中的 pattern 是以通配符开始的,需要使用单引号
4.子目录存储
通过spring.cloud.config.server.git.searchPaths
来定位到Git仓库的子目录中,相当于在uri后加上searchPaths的目录。
searchPaths参数的配置也支持使用{应用名}、{环境名}、{分支名}占位符,比如spring.cloud.config.server.git.searchPaths={应用名}
,通过这样的配置,我们能让每一个应用匹配到自己的目录中。如下举例:
spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
searchPaths: '{application}'
5.访问权限
使用Git仓库的时候,使用HTTP认证需要使用username和password属性来配置账户,具体如下:
(还可以使用SSH认证,Config Server本地的.ssh文件或使用私钥等进行配置,如:http://cloud.spring.io/spring-cloud-static/Finchley.RELEASE/single/spring-cloud.html#_git_ssh_configuration_using_properties)
代码语言:javascript复制spring:
cloud:
config:
server:
git:
uri: https://github.com/spring-cloud-samples/config-repo
username: trolley
password: strongpassword
(三)基本的手动刷新和结合Spring Cloud Bus热刷新
为了避免重启项目才能获取最新的配置信息,可以进一步优化做到手动刷新和结合Spring Cloud Bus进行热刷新,其基本要求一般不改动服务端相关配置和代码,但是需要各客户端增加断点访问依赖和安全依赖,这样就可以对外通过访问客户端刷新断点uri来进行刷新操作,手动刷新就是直接访问断点的方式,虽然简单,但是如果每次都要手动刷新的话,面对微服务很多的情况下,就会因为操作人员忘记或者遗漏的情况,从而造成服务出错。在生产实践中,我们往往要求结合Spring Cloud Bus进行热刷新。
结合Spring Cloud Bus进行热刷新的操作如上图所示,用户更新配置信息时,检查到Git Hook变化,触发Hook配置地址的调用,Config Server接收到请求并发布消息,Bus将消息发送到Config Client,当Config Client接收到消息后重新发送请求加载配置消息。
四、Spring Cloud Config结合关系型数据库MYSQL实现配置中心方案
(一)基本实现原理
Spring Cloud Config是一个独立的配置中心,支持多种存储配置信息形式,其中包括jdbc方式,其基本原理图如下:
git有它天然的优势,比如多版本管理、分支管理、提交审核策略等等,但是如果相对其中存储的数据做细粒度的权限控制,就力不从心了。我们可以将持久化从git迁移到MySQL上,这样的好处就是,可以针对配置中心,方便开发出一些对外接口,例如一些用户可配置的动态改更新的参数,同时,由于是数据库方式,当让可以自己在此基础上实现视图化和刷新机制,整体上显得更加优雅。
(二)基本要求讲解
具体实现上,需要Config Server端增加服务中心jar包、-配置中心jar包、连接msql数据库相关jar包这三个必须的jar包,在配置文件中需要增加对应的服务名称、连接配置信息、mysql 属性配置、指定注册中心地址等,具体我们要分析的是连接配置信息:
代码语言:javascript复制#连接配置信息
spring:
application:
name: config-server-jdbc
profiles:
active: jdbc
cloud:
config:
server:
default-label: dev
jdbc:
sql: SELECT akey , avalue FROM config_server where APPLICATION=? and APROFILE=? and LABEL=?
连接配置信息中:
- spring.profiles.active=jdbc ,自动实现JdbcEnvironmentRepository。
- sql语句自定义,否则会默认为“SELECT KEY, VALUE from PROPERTIES where APPLICATION=? and PROFILE=? and LABEL=?”,具体可以参考 JdbcEnvironmentRepository 实现。非必须,这里由于采用mysql数据源,
key
、value
是保留关键词,原生的实现语句会报错,所以需要重写一下这句查询语句(如果存储的表结构设计不同于上面准备的内容,也可以通过这个属性的配置来修改配置的获取逻辑) - 数据库建表为config_server,由于key,value和profile是mysql关键字,所以都在最前面加了a。当然表名字段名都可以自定义。
- {application} 对应客户端的”spring.application.name”属性;
- {aprofile} 对应客户端的 “spring.profiles.active”属性(逗号分隔的列表);
- {label} 对应服务端属性,这个属性能标示一组配置文件的版本.
- 只要 select出来是两个字段 ,框架会 自动包装到environment的map<key,value> 。
然后便是启动类等注解配置和数据库相关操作与构建,相关代码具体见后面博客及github。
注意,JDBC存储的使用思路,具体使用实际上还有很多可以优化的空间,比如:索引的优化、查询语句的优化;如果还需要进一步定制管理,对于表结构的优化也是很有必要的。
五、Spring Cloud Config结合非关系性数据库MongoDB实现配置中心方案
(一)基本实现原理
Spring Cloud Config作为独立的配置中心,支持多种存储配置信息形式,但是没有提供MongoDB的方式,但是目前已经有相关孵化器,其基本原理图如下:
其基本原理与关系型数据库原理相类似,相关代码具体见后面博客及github。
(二)基本要求讲解
具体实现上,需要Config Server端增加服务中心jar包、-配置中心jar包、连接mongo数据库相关jar包这三个必须的jar包,在配置文件中需要增加对应的服务名称、连接配置信息、mongo属性配置、指定注册中心地址等,相关代码具体见后面博客及github。
六、Spring Cloud Config使用技能及功能扩展
(一)基本实用技能:本地参数覆盖远程参数
主要是指使用本地的参数覆盖远程的参数,这在开发的时候经常会用到,主要配合内容如下:
代码语言:javascript复制spring:
cloud:
config:
allowOverride: true
overrideNone: true
overrideSystemProperties: false
这三个属性的意思是:
- spring.cloud.config.allowOverride:如果想要远程配置优先级高,那么allowOverride设置为false;如果想要本地配置优先级高那么allowOverride设置为true,默认为true;
- spring.cloud.config.overrideNone:overrideNone为true时本地配置优先级高,包括系统环境变量、本地配置文件等等,默认为false;
- spring.cloud.config.overrideSystemProperties:只有系统环境变量或者系统属性才能覆盖远程配置文件的配置,本地配置文件中配置优先级低于远程配置,默认为true。
(二)客户端自动刷新实现
在一些应用上面,不需要在服务端批量推送的时候,客户端本身需要获取变化参数的情况,这个时候需要使用客户端自动刷新来完成该功能。具体实现上,可以单独在二方包中增加一个用于自动刷新的功能,引入spring-cloud-config-client和spring-cloud-autoconfigure,并且增加自动配置类(增加间隔刷新时间),在该类中主要注入端点类,通过定时任务和刷新时间,进行配置请求刷新,添加配置后,我们将二方包引入到实际的客户端应用中。
在客户端中需要引入spring-cloud-config-client、spring-boot-starter-security和我们刚刚新做的二方包,并且在对应的配置文件中增加spring.cloud.config.refreshInterval内容,写一个相关的控制器便可以开始测试了,相关代码具体见后面博客及github。
(三)客户端回退功能实现
客户端可以匹配回退机制,主要用于以下两种场景,应用回退手段来处理案例:
- 因为一定原因出现了网络中断的情况;
- 配置服务因为一定的原因进行维护而关闭。
当启用回退时,客户端适配器将“缓存”本地文件系统中的计算属性。要启用回退功能,只需要指定存储缓存的位置即可。
在具体实现上,我们同样需要在二方包增加对应可以实现客户端回退功能的内容,引入spring-cloud-config-client和spring-security-rsa,增加自动配置类(包含回退本地配置文件所在的文件和名称、要回退配置文件的路径、用来创建本地回退文件的方法)和相关配置内容,
(四)客户端安全认证机制JWT实现
Spring Cloud Config客户端使用JWT身份验证方法代替标准的基本身份验证,这种方式需要对服务端和客户端都要改造,具体如下:
- 客户端向服务端授权Rest Controller发送请求并且带上用户名和密码;
- 服务端返回JET Token;
- 客户端查询服务端的配置需要在Header中带上token令牌进行认证。
在具体实现上,需要在二方包中引入jwt相关内容,并将该二方包作为基本包使用,在此二方包中pom中必须需要引入一下这三项内容spring-boot-autoconfigure、spring-boot-autoconfiguration-processor、spring-cloud-starter-config,创建Config配置类(引入标示username和password以及endpoint内容,同时增加初始化init并采用注解@PostConstruct,表明在Servelt构造函数和Init()方法之间执行具体容器加载),并进一步创建实体类LoginRequest(对应请求username和password)和实体类Token(对应生成的token)。
将此二方包引入到客户端的pom中,同时引入spring-cloud-config-client,并且在对应bootstrap文件中添加用于参与安全认证所需要的username、password、endpoint(是一个http地址,config server的访问授权地址)。增加启动类和控制器进行测试。
接下来就需要对服务端的代码进行分析和讨论了,首先,需要在pom中引入spring-cloud-config-server、jwt、gson、spring-boot-starter-security,创建JwtAuthenticationRequest类用于传递用户名和密码,创建JwtAuthenticationResponse实体类返回token信息,创建JwtUser用户认证信息实体类,创建JWT的token认证过滤器和JWT工具类(用于生成token和token验证),创建JWT认证端点类(在认证过程中,未能认证通过的直接返回401状态码),接着创建一个认证账号的验证类MemberServiceImpl及将数据封装为json返回客户端的WebAuthenticationDetailsSourceImpl,最后创建Config进行安全和过滤的自动配置类,增加控制器用于测试,相关代码具体见后面博客及github。相关具体类调用时序图如下:
七、Spring Cloud Config实现客户端及服务端高可用方案
(一)客户端高可用原理及方案
客户端的高可用方式,从方案角度来看,主要还是用file的形式,和前面客户端的回退方案思路大致一样,客户端高可用主要是解决当服务端不可用的情况下,在客户端仍然可以正常启动。从客户端的角度出发,不是增加配置中心的高可用性,而是降低客户端对配置中心的依赖程度,从而提高整个分布式架构的健壮性。
具体实现上,仍然需要创建一个二方包,在二方包中引入spring-cloud-config-client,并且配置属性加载类,创建配置类命名为ConfigSupportConfiguration(主要是用于判断远程加载信息是否可用,如果不能用则将读取加载本地配置文件启动),同时在二方包中增加配置文件spring.factories指明org.springframework.cloud.bootstrap.BootstrapConfiguration。
将该二方包引入对应的客户端的pom中,同时引入spring-cloud-config-client,在bootstrap文件中增加backup开关并指明你备份的本地地址fallbackLocation,增加对应的启动类和控制器用于测试,相关代码具体见后面博客及github。
(二)服务端高可用原理及方案
服务端的高可用在生产环境中也一样重要,通过结合Eureka注册中心的方式来搭建Spring Cloud Config Server高可用,通过Ribbon的负载均衡选择一个Config Server进行连接来获取配置信息,具体流程见上图。
具体实现上,Eureka相关开发与之前是一样的,不用做多余的代码工作;服务端的pom文件中需要引入spring-cloud-config-server和spring-cloud-starter-netflix-eureka-client,其他按照之前的开发即可;客户端的pom文件中需要引入spring-cloud-config-client和spring-cloud-starter-netflix-eureka-client,并且在bootstrap中不在配置spring.cloud.config.uri信息用于指定Server端地址,而是增加了三个新的配置,具体如下:
- spring.cloud.config.discovery.enabled:开启Config服务发现支持;
- spring.cloud.config.discovery.serviceId:指定Server端的name,也就是Server端spring.application.name;
- euraka.client.service-url.defaultZone:只想注册中心的地址。
接着,按照以往的流程测试高可用就可以了,相关代码具体见后面博客及github。
八、Spring Cloud Config与Apollo配置使用实现界面化操作
(一)Apollo基本概述及基本功能介绍
1.Apollo简介
Apollo(阿波罗)是携程框架部研发并开源的一款生产级的配置中心产品,它能够集中管理应用在不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
Apollo目前在国内开发者社区比较热,在Github上有超过5k颗星,在国内众多互联网公司有落地案例,可以说Apollo是目前配置中心产品领域Number1的产品,其成熟度和企业级特性要远远强于Spring Cloud体系中的Spring Cloud Config产品。
Apollo采用分布式微服务架构,它的架构有一点复杂,Apollo的作者宋顺虽然给出了一个架构图,但是如果没有一定的分布式微服务架构基础的话,则普通的开发人员甚至是架构师也很难一下子理解。
2.Apollo基本功能介绍
- 统一管理不同环境、不同集群的配置:Apollo提供了一个统一界面集中式管理不同环境(environment)、不同集群(cluster)、不同命名空间(namespace)的配置;同一份代码部署在不同的集群,可以有不同的配置,比如zk的地址等;通过命名空间(namespace)可以很方便的支持多个不同应用共享同一份配置,同时还允许应用对共享的配置进行覆盖
- 配置修改实时生效(热发布): 用户在Apollo修改完配置并发布后,客户端能实时(1秒)接收到最新的配置,并通知到应用程序
- 版本发布管理: 所有的配置发布都有版本概念,从而可以方便地支持配置的回滚
- 灰度发布: 支持配置的灰度发布,比如点了发布后,只对部分应用实例生效,等观察一段时间没问题后再推给所有应用实例
- 权限管理、发布审核、操作审计:应用和配置的管理都有完善的权限管理机制,对配置的管理还分为了编辑和发布两个环节,从而减少人为的错误。 所有的操作都有审计日志,可以方便的追踪问题
- 客户端配置信息监控: 可以在界面上方便地看到配置在被哪些实例使用
- 提供Java和.Net原生客户端:提供了Java和.Net的原生客户端,方便应用集成;支持Spring Placeholder, Annotation和Spring Boot的ConfigurationProperties,方便应用使用(需要Spring 3.1.1 );同时提供了Http接口,非Java和.Net应用也可以方便的使用
- 提供开放平台API:Apollo自身提供了比较完善的统一配置管理界面,支持多环境、多数据中心配置管理、权限、流程治理等特性。不过Apollo出于通用性考虑,对配置的修改不会做过多限制,只要符合基本的格式就能够保存。对于有些使用方,它们的配置可能会有比较复杂的格式,而且对输入的值也需要进行校验后方可保存,如检查数据库、用户名和密码是否匹配。对于这类应用,Apollo支持应用方通过开放接口在Apollo进行配置的修改和发布,并且具备完善的授权和权限控制。
- 部署简单:配置中心作为基础服务,可用性要求非常高,这就要求Apollo对外部依赖尽可能地少。目前唯一的外部依赖是MySQL,所以部署非常简单,只要安装好Java和MySQL就可以让Apollo跑起来。Apollo还提供了打包脚本,一键就可以生成所有需要的安装包,并且支持自定义运行时参数
(二)Apollo总体架构模块分析
总体架构模块如下图所示:
其主要包含了四个核心模块和三个辅助模块:
1.四个核心模块及其主要功能
- ConfigService:提供配置获取接口、配置推送接口,服务于Apollo客户端;
- AdminService:提供配置管理接口、配置修改发布接口,服务于管理界面Portal;
- Client:为应用获取配置,支持实时更新,通过MetaServer获取ConfigService的服务列表,使用客户端软负载SLB方式调用ConfigService
- Portal:配置管理界面,通过MetaServer获取AdminService的服务列表,使用客户端软负载SLB方式调用AdminService
(ConfigService和AdminService都是多实例无状态的部署,需要将自身注册到Eureka中并保持心跳)
2.三个辅助服务发现模块
- Eureka:用于服务发现和注册,Config/AdminService注册实例并定期报心跳,和ConfigService在一起部署
- MetaServer:Portal通过域名访问MetaServer获取AdminService的地址列表,Client通过域名访问MetaServer获取ConfigService的地址列表。相当于一个Eureka Proxy,逻辑角色和ConfigService在一起部署
- NginxLB:和域名系统配合,协助Portal访问MetaServer获取AdminService地址列表;和域名系统配合,协助Client访问MetaServer获取ConfigService地址列表;和域名系统配合,协助用户访问Portal进行配置管理
Apollo可以和Spring Cloud Config搭建的微服务进行无缝集成。
3.为什么选择Eureka作为服务注册中心,而不是使用传统的zk、etcd呢?
有以下几方面的原因:
- 它提供了完整的Service Registry和Service Discovery实现。首先是提供了完整的实现,并且也经受住了Netflix自己的生产环境考验,相对使用起来会比较省心。
- 和Spring Cloud无缝集成:项目本身就使用了Spring Cloud和Spring Boot,同时Spring Cloud还有一套非常完善的开源代码来整合Eureka,所以使用起来非常方便。另外,Eureka还支持在我们应用自身的容器中启动,也就是说我们的应用启动完之后,既充当了Eureka的角色,同时也是服务的提供者。这样就极大的提高了服务的可用性。这一点是我们选择Eureka而不是zk、etcd等的主要原因,为了提高配置中心的可用性和降低部署复杂度,我们需要尽可能地减少外部依赖。
- Open Source:由于代码是开源的,所以非常便于了解它的实现原理和排查问题。
(三)Apollo客户端设计与运行环境介绍
1.Apollo客户端设计
Apollo客户端的实现原理:
- 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。
- 客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
这是一个fallback机制,为了防止推送机制失效导致配置不更新
客户端定时拉取会上报本地版本,所以一般情况下,对于定时拉取的操作,服务端都会返回304 – Not Modified
定时频率默认为每5分钟拉取一次,客户端也可以通过在运行时指定System Property: apollo.refreshInterval来覆盖,单位为分钟。
- 客户端从Apollo配置中心服务端获取到应用的最新配置后,会保存在内存中
- 客户端会把从服务端获取到的配置在本地文件系统缓存一份
在遇到服务不可用,或网络不通的时候,依然能从本地恢复配置
- 应用程序可以从Apollo客户端获取最新的配置、订阅配置更新通知
2.配置更新推送实现
Apollo客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。长连接实际上我们是通过Http Long Polling实现的,具体而言:
- 客户端发起一个Http请求到服务端
- 服务端会保持住这个连接30秒
- 如果在30秒内有客户端关心的配置变化,被保持住的客户端请求会立即返回,并告知客户端有配置变化的namespace信息,客户端会据此拉取对应namespace的最新配置
- 如果在30秒内没有客户端关心的配置变化,那么会返回Http状态码304给客户端
- 客户端在服务端请求返回后会自动重连
考虑到会有数万客户端向服务端发起长连,在服务端使用了async servlet(Spring DeferredResult)来服务Http Long Polling请求。
3.环境要求
- Java1.7
- Guava15.0 : Apollo客户端默认会引用Guava 19,如果你的项目引用了其它版本,请确保版本号大于等于15.0
- 注:对于Apollo客户端,如果有需要的话,可以做少量代码修改来降级到Java 1.6
Apllo这部分的内容目前我还没有在实践中应用,所以后续博客和github中可能暂不停工代码分析。
参考书籍、文献和资料:
【1】郑天民. 微服务设计原理与架构. 北京:人民邮电出版社,2018.
【2】徐进,叶志远,钟尊发,蔡波斯等. 重新定义Spring Cloud. 北京:机械工业出版社. 2018.
【3】https://blog.csdn.net/xiaofeng10330111/article/details/85682513.
【4】http://blog.sina.com.cn/s/blog_17ea544680102xive.html.
【5】https://www.cnblogs.com/hellxz/p/9306507.html.
【6】https://www.jb51.net/article/147212.htm.
【7】https://blog.csdn.net/hjbbjh0521/article/details/80363947.
【8】http://blog.didispace.com/spring-cloud-starter-edgware-3-1/.
【9】https://blog.csdn.net/john1337/article/details/82413837.
【10】https://blog.csdn.net/zjh_746140129/article/details/86179522.
【11】https://blog.csdn.net/ningjiebing/article/details/90638974.
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/125889.html原文链接:https://javaforall.cn