1. 配置中心Config
随着项目日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,需要的配置文件随着服务增加而不断增多。某一个基础服务信息变更,都会引起一系列的更新和重启,运维苦不堪言也容易出错。配置中心就是是解决此类问题的。
市面上开源的配置中心有很多,BAT每家都出过,360的QConf、淘宝的diamond、网络郑烂的disconf都是解决这类问题。国外也有很多开源的配置中心Apache Commons Configuration、owner、cfg4j等等。
为分布式系统中的基础设施和微服务应用提供集中化的外部配置支持,它分为服务端与客户端两个部分。其中服务端也称为分布式配置中心者丛滑,它是一个独立的微服务应用,用来连接配置仓库并为客户端提供获取配置信息、加密 / 解密信息等访问接口;而客户端则是微服务架构中的各个微服务应用或基础设施,它们通过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。
由于 Spring Cloud Config 实现的配置中心默认采用 Git 来存储配置信息,所以使用 Spring Cloud Config 构建的配置服务器,天然就支持对微服务应用配置信息的版本管理,并且可以通过 Git 客户端工具来方便的管理和访问配置内容。当然它也提供了对其他存储方式的支持,比如:SVN 仓库、本地化文件系统。
pom.xml中引入 spring-cloud-config-server 依赖,完整依赖配置如下:
创建Spring Boot的程序主类,并添加 @EnableConfigServer 注解,开启Config Server
application.properties`中配置服务信息以及git信息,例如:
Spring Cloud Config也提供 本地存储配置 方式。我们只需要设置属性spring.profiles.active=native,Config Server会默认从应用的src/main/resource目录下检索配置文件。也可以通过spring.cloud.config.server.native.searchLocations=file:F:/properties/属性来指定配置文件的位置。
准备一个 Git 仓库,在 上面创建了一个文件夹 config-repo 用来存放配置文件,为了模拟生产环境,我们创建以下三个配置文件:
其中设置了一个from属性,为每个配置文件分别设置了不同的值,如:
为了测试版本控制,在master中,我们都加入1.0的后缀,同时创建一个 config-label-test分支 ,并将各配置文件中的值用2.0作为后缀。
URL与配置文件的映射关系如下:
上首腊面的url会映射 {application}-{profile}.properties ** 对应的配置文件, {label} 对应git上不同的分支,默认为master。 先找给定名称的配置文件,如果找不到去application.yml/application.properties找
尝试构造不同的url来访问不同的配置内容,比如:要访问config-label-test分支,应用的prod环境,可以通过这个url: http://localhost:7001/application/prod/config-label-test
创建一个Spring Boot应用,在pom.xml中引入spring-cloud-starter-config依赖,完整依赖关系如下:
搭建srpingcloud-config server端,配置文件可以用application.yml 或 application.properties,config client端却要使用bootstrap.yml或bootstrap.properties。
格外注意(config client端) :上面这些属性必须配置在 bootstrap .properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而 bootstrap.properties的加载也是先于application.properties (bootstrap.yml 的加载也是先于 application.yml)。
创建一个Rest Api来返回配置中心的from属性,具体如下:
启动该应用,并访问: http://localhost:6020/from ,我们就可以根据配置内容输出对应环境的from内容了。
有时,我们需要对配置内容做一些实时更新。server端会自动读取最新提交的内容,client端不会自动获取新的信息。
将config-server和config-client都启动起来,并访问客户端提供的REST API http://localhost:6020/from 来获取配置信息,可以获得返回内容为: git-dev-1.0 。接着,我们可以尝试使用Git工具修改当前配置的内容,比如,将 config-repo/application-dev.properties 中的from的值从 from=git-dev-1.0 修改为 from=git-dev-2.0 ,再访问 http://localhost:6020/from ,可以看到其返回内容还是 git-dev-1.0 。
下面进行改造:在config-client端增加一些内容和操作以实现配置的刷新
在config-clinet的 pom.xml 中新增 spring-boot-starter-actuator 监控模块,其中包含了 /refresh 刷新API。
增加spring-boot-starter-actuator 包,这是一套监控的功能,可以监控程序在运行时状态,其中就包括 /actuator/refresh`的功能。
需要给 加载变量的类上 面加载 @RefreshScope ,在客户端执行 /actuator/refresh 的时候就会更新此类下面的变量值。
Spring Boot 1.5.X 以上默认开通了安全认证,所以要在配置文件 application.yml 中添加以下配置以将 /actuator/refresh 这个 Endpoint 暴露出来
改造完之后,我们以 POST 请求的方式来访问 http://localhost:6020/actuator/refresh 就会更新配置文件至最新版本。
加载 bootstrap. ------>连接config server 加载远程设置 --------> 加载application.的配置**
bootstrap 放一些你不想改的值
本地配置和远程配置冲突 以远程的为准
2. Disconf原理及分布式配置中心的一般实现思路
因为新公司没有采用独立的配置中心,每次修改配置参数只能通过手动修改配置文件的方式,然后再重启重启重启,而且机器又是多台,这种方式无疑是非常低下的,而且极容易出错,所以才有了下面的配置中喊陪心选型。
其实自己开发一个简单的配置中心也是非常容易的,基于redis+DB就能简单实现。但是要设计一个合格的配置中心还需要考虑如下几点:
所以要自己开发一个独立的配置中心,还是要考虑得比较全面的。而且项目还是以业务为主,也没有足够人力来重新开发一套配置中心,所以就打算借助于开源的力量来满足目前的使用场景。
因为现在的配置中心还是有一些开源实现的。像网络的Disconf,阿里的Diamond,携程的Apollo,还有基于Github的pull模式来实现。我为什么选择Disconf,主要有下面几个点的考量:
Disconf是网络的一个分布式配置中心,目前已经开源。而且它是基于java实现的,有简单的配置页面,而且官方还提供了一个相对完善的 文档 .开发者只需按照它上面的步骤来即可安装,但是官网的安装文档比较扯淡,总结起来就是如下几点:
然后启动Nginx.
Disconf主要是依靠zookeeper的Watch机制来做配置实时修改的,我们都知道ZK是通过目录挂载的方式来做服务的自粗渗拦动注册与发布。客户端启动时注册了一个回调接口,当zk目录发生变化时会回调所有客户端节点,从而做到"实时"更新配置的目的。
在配置中心添加的配置数据都被持久化到了DB中,每次客户端启动的时候会调用Disconf的Http接口获取最新的配置数据,如果网络不通,默认会重试三次,如果还不通,则抛出异常。如果第一次拉取配置就有问题,作为配置中心来讲是肯定是无解的,需要客户端去解决(一般这种情况是网络问题或者配置中心服务不可用导致)。
我们这里不需要考虑第一次加载配置就失败的情况.那么问题来了:
答案:不会,因为disconf会单独起一个线程做重连操作。岩胡
答案:没有做这方面的保证。因为客户端连接到配置中心上以后会将机器名挂载到zk目录下,可以通过界面查看配置使用的机器数。
所以要使用一个开源产品,还是要尽可能的掌握它,如果有太多未知因素在里面的话,出了问题很难被发现,对自己也是一个提升。
3. Apollo配置中心 原理分析
大致过程:
①笑谈谨 用户在Portal操作配置发布
② Portal调用Admin Service的接口操作发布
③ Admin Service发布配置后,发送ReleaseMessage给各个Config Service
④ Config Service收到ReleaseMessage后,通知对应的客户端
发送侍颤ReleaseMessage的实现方式
Config Service通知客户端的实现方式
实现原理:
① 客户端和服务端保持了一个长连接,从而能第一时间获得配置更新的推送。(通过Http Long Polling实现)
② 客户端还会定时从Apollo配置中心服务端拉取应用的最新配置。
Apollo在Spring环境下实现配置优先级原理
此种引入apollo-client客户端之后,启动类加上@EnableApolloConfig,如果有涉及到属性发布,即可刷新
以碰基@ConfigurationProperties得形式得属性,需要额外添加监听器Bean,方法上加上注解@ApolloConfigChangeListener。例如:
4. 简述软件配置的管理中心思想
(1)《ISO/IEC 12207(1995)信息技术--软件生存期过程》:配置管理过程是在整个软件生存期中实施管理和技术规程的过程,它标识、定义系统中软件项并制定基线;控制软件项的修改和发行;记录和报告软件项的状态和修改申请;保证软件项的完整性、协调性和正确性;以及控制软件项的储存、装载和交付。
(2)《ISO 9000-3(1997)质量管理和质量保证标准--第3部分:ISO 9001:1994 在计算机软件开发、供应、安装和维山稿肆护中的使用指南》:软件配置管理是一个管理学科,它对配置项的开发和支持生存期给予技术上和管理上的指导。配置管理的应用取决于项目的规模、复杂程度和风险大逗轿小。(3)巴比齐(W.BaBIch):软件配置管理能协调软件开发,使得混乱减少到最小。软件配置管理是一种标识、组织和控制修改的技术,目的是最有效地提高生产率。
(4)《GB/T 11457(1995)软件工程术语》:软件配置管理是标识和确定系统中配置项敬困的过程,在系统整个生存周期内控制这些项的投放和更动,记录并报告配置的状态和更动要求,验证配置项的完整性和正确性。一言以蔽之,配置管理是门通过一系列技术、方法和手段来维护产品的历史、鉴别和定位产品独有的版本、在产品开发和发布阶段控制变化,从而使管理制度化、有效减少重复性工作、保证产品的质量和效率的科学。
5. Spring Cloud 之配置中心
配置服务器默认采用git来存储配置信息,也可以本地存储。
1. pom.xml中加入spring-cloud-config-server,spring-cloud-starter-eureka
2. 主类中配置@EnableConfigServer @EnableEurekaClient
3. application.yml配置
spring.application.name=config-server
server.port=60002
eureka.client.serviceUrl.defaultZone=http://localhost:10001/eureka/
4. 若租缓使用本地存储:
spring.profiles.active=native
spring.cloud.config.server.native.search-locations=classpath:/config
在resource目录下创建config目录,里面配置clientA-dev.yml,clientA-test.yml等
5. 若使用git存储:
spring.cloud.config.server.git.uri=http://git.oschina.net/didispace/SpringBoot-Learning/
spring.cloud.config.server.git.searchPaths=Chapter9-1-4/config-repo
spring.cloud.config.server.git.username=username
spring.cloud.config.server.git.password=password
uri:配置git仓库位置;searchPaths:配置仓库路径下的相对搜索位置,可以配置多个;username:访问git仓库的用户名;password:访问git仓库的用户密码
1. pom.xml中加入spring-cloud-starter-eureka,spring-cloud-starter-config
2. spring.application.name=clientA
spring.cloud.config.enabled=true
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=config-server
spring.cloud.config.profile=dev
spring.cloud.config.label=master
eureka.client.serviceUrl.defaultZone=http://localhost:10001/eureka/
解释:
配置中心的{application}-{profile}.properties配置文件,{label}对应git上不同的分支,默认为master。
spring.application.name:对应{application}部分
spring.cloud.config.profile:对应{profile}部分
spring.cloud.config.label:对应git的分支。如果配滚首置中心使用的是本地存储,则该参数无用
spring.cloud.config.uri:配置中心的具体地址(不建议使用,因为不利于负载均衡)
spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。
特别注意:上面这些与弊备模spring-cloud相关的属性必须配置在bootstrap.properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties。例如上面的defaultZone如果不配置,则找不到service-id,会导致启动失败。
1. config-server主类配置@EnableEurekaClient,并启动多个,相当于有多个配置中心注册在服务中心;
2. config-client的properties配置中使用spring.cloud.config.discovery.service-id指定config-server,实现负载均衡。如此,任意一个config-server节点crash了也不影响config-client的运行。
配置中心的数据修改后,客户端可实时获取更新内容,实现方式:
1. config-client的pom.xml中新增spring-boot-starter-actuator监控模块,其中包含了/refresh刷新API。
2. git中配置数据修改后,config-client中执行http://localhost:18443/refresh 即可实现client端配置数据更新
实例源码: config-server