一、简介
在分布式系统中,由于服务数量巨多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。
随着线上项目变的日益庞大,每个项目都散落着各种配置文件,如果采用分布式的开发模式,需要的配置文件随着服务增加而不断增多。某一个基础服务信息变更,都会引起一系列的更新和重启,运维苦不堪言也容易出错。配置中心便是解决此类问题的灵丹妙药。
市面上开源的配置中心有很多,BAT每家都出过,360的QConf、淘宝的diamond、百度的disconf都是解决这类问题。国外也有很多开源的配置中心Apache的Apache Commons Configuration、owner、cfg4j等等。
二、配置中心提供的核心功能
- 提供服务端和客户端支持
- 集中管理各环境的配置文件
- 配置文件修改之后,可以快速的生效
- 可以进行版本管理
- 支持大的并发查询
- 支持各种语言
Spring Cloud Config可以完美的支持以上所有的需求。
Spring Cloud Config项目是一个解决分布式系统的配置管理方案。它包含了Client和Server两个部分,server提供配置文件的存储、以接口的形式将配置文件的内容提供出去,client通过接口获取数据、并依据此数据初始化自己的应用。Spring cloud使用git或svn存放配置文件,默认情况下使用git,我们以git为例。
首先在github上面创建了一个文件夹 config-files用来存放配置文件,为了模拟生产环境,我们创建以下三个配置文件:
// 开发环境
mengma-config-dev.yml
// 测试环境
mengma-config-test.yml
// 生产环境
mengma-config-pro.yml
每个配置文件中都写一个属性 hello ,属性值分别是 mengma.....dev / mengma.....test / mengma.....pro 。下面我们开始配置config server 端。
config server 端代码编写
- 新建项目,引入依赖,只需要引入 config -server 就可以 ,不需要引入 eureka-client ,web
config-server
- 配置配置文件
server:
port: 8778
spring:
application:
name: config-server
cloud:
config:
server:
git:
uri: https://github.com/*** # 配置git仓库的地址
search-paths: config-files # git仓库地址下的相对地址,可以配置多个,用,分割。
username: *** # git仓库的账号
password: **** # git仓库的密码
- 启动类添加注解
@SpringBootApplication
// 声明为 config server 端
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
- 测试config server 是否生效
首先我们先要测试server端是否可以读取到github上面的配置信息,直接访问:http://localhost:8778/mengma-config/dev
返回信息如下:
{
"name": "mengma-config",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "https://github.com/****/config-files/mengma-config-dev.yml",
"source": {
"hello": "mengma.....dev"
}
}
]
}
上述的返回的信息包含了配置文件的位置、版本、配置文件的名称以及配置文件中的具体内容,说明server端已经成功获取了git仓库的配置信息。
如果直接查看配置文件中的配置信息可访问:http://localhost:8778/mengma-config-dev.yml,
返回:
hello: mengma.....dev
修改配置文件mengma-config-dev.yml中配置信息为:hello: mengma.....dev update,再次在浏览器访问http://localhost:8778/mengma-config-dev.yml,返回:
hello: mengma.....dev update、
说明 server 端会自动读取最新提交的内容。
仓库中的配置文件会被转换成web接口,访问可以参照以下的规则:
- /{application}/{profile}[/{label}]
- /{application}-{profile}.yml
- /{label}/{application}-{profile}.yml
- /{application}-{profile}.properties
- /{label}/{application}-{profile}.properties
以config-server-dev.yml为例子,它的 application
是 config-server
,profile
是dev
,client会根据填写的参数来选择读取对应的配置。
label?.....
以config-server-dev.yml为例子,它的application是config-server,profile是dev。client会根据填写的参数来选择读取对应的配置。
client 端
主要展示如何在业务项目中去获取server端的配置信息。
添加依赖
spring-cloud-starter-config
spring-boot-starter-web
spring-boot-starter-test配置文件
需要配置两个配置文件,application.properties和bootstrap.properties(文件加载优先权)
application.properties如下:
spring.application.name=spring-cloud-config-client
server.port=8002
bootstrap.properties如下:
spring.application.name=config-client
spring.cloud.config.label=master
spring.cloud.config.profile=dev
spring.cloud.config.uri= http://localhost:xxxx/
server.port=8881
- spring.cloud.config.label 指明远程仓库的分支
- spring.cloud.config.profile
dev开发环境配置文件
test测试环境
pro正式环境 - spring.cloud.config.uri= http://localhost:8888/ 指明配置服务中心的网址。
程序的入口类,写一个API接口“/hi”,返回从配置中心读取的 hello
变量的值,代码如下:
@SpringBootApplication
@RestController
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
@Value("${hello}")
String hello;
@RequestMapping(value = "/hi")
public String hi(){
return hello;
}
}
打开网址访问:http://localhost:8881/hi,网页显示:
mengma.....dev
这就说明,config-client从config-server获取了foo的属性,而config-server是从git仓库读取的,如图:
配置中心服务高可用
客户端都是直接调用配置中心的server端来获取配置文件信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果server端要做集群,客户端只能通过原始的方式来路由,server端改变IP地址的时候,客户端也需要修改配置,不符合springcloud服务治理的理念。springcloud提供了这样的解决方案,我们只需要将server端当做一个服务注册到eureka中,client端去eureka中去获取配置中心server端的服务既可。
这篇文章我们基于配置中心git版本的内容来改造。
server 端改造
- 添加依赖
添加 eureka-client 依赖,来添加对eureka 的支持。
- 配置文件
server:
server:
port: 8001
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/***/spring-cloud-starter/ # 配置git仓库的地址
search-paths: config-repo # git仓库地址下的相对地址,可以配置多个,用,分割。
username: username # git仓库的账号
password: password # git仓库的密码
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 注册中心eurka地址
增加了eureka注册中心的配置。
这样server端的改造就完成了。先启动eureka注册中心,在启动server端,在浏览器中访问:http://localhost:xxxx/ 就会看到server端已经注册了到注册中心了。
客户端改造
依赖添加
添加 eureka-client配置文件
spring:
cloud:
config:
discovery:
serviceId: spring-cloud-config-server
enabled: true
profile: dev
name: neo-config
label: master
application:
name: spring-cloud-config-client
server:
port: 8002
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/
主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最后的三个配置:
spring.cloud.config.discovery.enabled :开启Config服务发现支持
spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
eureka.client.serviceUrl.defaultZone :指向配置中心的地址
这三个配置文件都需要放到bootstrap.yml的配置中。
启动client端,在浏览器中访问:http://localhost:xxxx/ 就会看到server端和client端都已经注册了到注册中心了。
高可用
为了模拟生产集群环境,我们改动server端的端口为8003,再启动一个server端来做服务的负载,提供高可用的server端支持。
如上图就可发现会有两个server端同时提供配置中心的服务,防止某一台挂掉之后影响整个系统的使用。
我们先单独测试服务端,分别访问:http://localhost:8001/neo-config/dev、http://localhost:8003/neo-config/dev返回信息:
再次访问:http://localhost:8002/hello,返回:mengma.....dev update。说明客户端已经读取到了server端的内容,我们随机停掉一台server端的服务,再次访问http://localhost:8002/hello,返回:mengma.....dev update,说明达到了高可用的目的。