在前文服务注册Eureka原理及集群配置中,我们配置Eureka集群时,可以通过--spring.profiles.active=peer1
来指定微服务在启动时使用哪段配置。但往往在微服务架构中,需要维护大量的配置文件,在开发、测试、生产环境,这些配置文件又有所不同,同时还希望能做到修改配置文件时,微服务能够不停止服务。
也就是说在微服务架构中,对于配置文件,通常有如下的需求
- 配置文件集中管理
- 不同环境不同配置
- 运行期间可动态调整配置
而Spring Cloud Config正是解决这问题的组件。
本文讲从基本配置步骤,动态刷新配置,以及Spring cloud config高可用三个三面讲解如何配置Spring cloud config.
配置步骤
如上图所示,用户将配置文件push到git仓库,配置文件按照{application}-{profile}.yml
或者{application}-{profile}.properties
格式命名。spring cloud config server连接git仓库,为所有config client(具体的微服务应用)提供配置服务。
config client 在配置文件中指向配置中心的地址。
准备配置文件
创建一个 spring-cloud-config
文件夹,文件夹下创建子文件夹config
,在子文件夹下创建以下四个文件,并上传本地gitlab仓库中http://gitlab.bill.com/billjiang/spring-cloud-config
- hello.yml
- hello-dev.yml
- hello-test.yml
- hello-production.yml
创建config server
分别对应默认、开发阶段、测试阶段、生成环境的配置文件,并在里面写入相应的内容,比如依次写入profile:defualt-1.0
、profile:dev-1.0
、profile:test-1.0
、profile:production-1.0
内容,以便后续测试。
下面configserver项目为例,演示spring cloud config的配置,本文示例代码参考springcloud-demo下的configserver
项目
- 创建configserver项目,引入如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
上面的pom.xml不仅引入了config-server还引入了security,主要是配置文件的信息比较重要,加上安全认证多个保障。
- 启动类上加上
@EnableConfigServer
和@EnableDiscoveryClient
注解
这个注解声明是config server,第二个注解是将其注册到注册中心,方便管理和横向扩展为集群。 - 在配置文件中,加上如下配置
spring:
cloud:
config:
server:
git:
uri: http://gitlab.bill.com/billjiang/spring-cloud-config.git
search-paths: config
username: billjiang
password: '{cipher}2c50a112807ec405695dac19c15cc6da280d8d70e9998b82a9f11d202a6fb7b4'
health:
repositories:
a-hello:
label: master
name: hello
profiles: dev
security:
basic:
enabled: true
user:
name: user
password: 123456
encrypt:
key: billjiang
这里对配置文件进行了对称加密,也可以对放入git仓库(我在本地搭建了个gitlab)的敏感信息进行加密,对于密文的生成可以在项目启动后,使用curl http://user:123456@localhost:8090/encrypt -d [明文]
这样可以在控制台生成密文,比如2c50a112807ec405695dac19c15cc6da280d8d70e9998b82a9f11d202a6fb7b4
,把生成的密文加上{cipher}
前缀即可作为对称加密的信息。其中encrypt.key
是对称加密的密钥。
需要注意的是:如果使用Dalston.SR2
版本的Spring.cloud 在使用curl http://user:123456@localhost:8090/encrypt -d [明文]
会报错,把Spring cloud换成Dalston.SR1
就能解决,这是Dalston.SR2
的一个bug。
启动项目后,使用http://localhost:8090/hello/dev
可返回如下信息,说明config server已经从git仓库中读取了hello-dev.yml
的配置信息
在浏览器输入http://localhost:8090/hello-dev.yml
还可以在界面输入配置文件的具体内容。
创建config client
下面以hello
项目改造为例,说下client端如何从config server中获取配置。
- 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
- 在配置文件
bootstrap.yml
中添加如下配置
spring:
application:
name: hello
cloud:
config:
uri: http://user:123456@localhost:8090/
profile: dev
label: master
之所以不在application.yml中配置,spring boot会优先加载bootstrap.yml,不然上下文中无法读取到配置而报错。这里指向了config server的地址,并且说明读取hello-dev.yml
的配置,读取的是master分支。
- 写一个测试的列子
@Value("${profile}")
private String profile;
@GetMapping("/profile")
public String profile(){
return this.profile;
}
- 启动
hello
项目,输入http://localhost:8000/profile
即可在界面上看到dev-1.0
的输出。说明客户端正常读取了指定的配置文件内容。
配置刷新
要在微服务运行期间动态刷新配置,可以通过调用/refresh
实现,但这样只能针对单个服务,而且要手动操作;如果通过消息中间件,可以将刷新事件广播到所有相关的微服务,从而做到自动刷新。
调用/refresh 刷新
- 引入依赖actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>1.5.6.RELEASE</version>
</dependency>`
- 配置文件中增加
endpoints:
refresh:
enabled: true
sensitive: false
- 修改配置文件
hello-dev.yml
内容,改为dev-1.0-refresh
,提交到gitlab中 - 执行
curl -X POST http://localhost:8000/refresh
或者用webhook提交该请求 - 浏览器输入
http://localhost:8000/profile
查看输出,发现内容已经更改为dev-1.0-refresh
使用Spring Cloud Bus自动刷新
借助Spring Cloud Bus,可以将配置变更事件广播到相关微服务,从而使得相关微服务能够自动刷新配置。
那么刷新的事件可以从单个的服务发起,这样可以将配置更新事件广播到同类服务集群,如果N个微服务集群要更新服务,那么也要操作N次。而从config server发起刷新,则所有相关集群自动刷新配置,后一种明显更好。
config-server 配置spring-cloud-bus
- 引入 spring-cloud-bus
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
- 配置文件bootstrap.yml新增
endpoints:
bus:
enabled: true
sensitive: false
spring:
rabbitmq:
host: localhost
port: 5673
username: guest
password: guest
- 启动项目
configserver
- 修改配置文件
hello-dev.yml
内容为dev-1.0-bus
并提交到gitlab - 执行
curl -X POST http://user:123456@localhost:8090/bus/refresh
刷新配置 - 浏览器输入
http://localhost:8000/profile
发现内容变为dev-1.0-bus
,说明自动化刷新已生效。
为了更好地测试上述效果,可以通过java -ar hello.jar --server.port=8001
,java -jar hello.jar --server.port=8002
命令将单个微服务配置成集群,同时配置其他集群。变更多个配置文件后,刷新配置,看看是否都更新了。
大家可以按照以上步骤,在单个服务节点上配置spring cloud bus,看看刷新配置后,集群中其他节点的配置是否同步更新了。
局部刷新
可以通过/bus/refresh?destination=customers:8000
,customers:8000
是注册在Eureka Server上的微服务ID,即ApplicationContextID.
Spring cloud config高可用
作为微服务架构中一个十分重要的服务节点,spring cloud config要保证高可用,就要避免单点。这里要分两种情况,如果cloud server已经注册到Eureka Server,则仅仅需要多部署几个cloud server形成集群。如果没有注册到Eureka Server,就需要通过负载均衡器,讲请求转发到cloud server集群。
当然,也要保证消息中间件RabbitMQ的高可用。
以上就是Spring Cloud Config的配置。