SpringCloud Config 分布式配置中心
1. 概述
微服务意味着要将单体应用中的业务拆分成一个一个子服务,每个服务的粒度相对较小,因此系统中会出现大量的 服务。由于每个服务都需要必要的配置才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。SpringCloud提供了Config Server来解决这个问题,SpringCloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。SpringCloud Config分为服务端和客户端两部分,服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口,将配置信息以REST接口的形式暴露给客户端(客户端可以用REST风格方式读取到该配置信息)。客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容。
如图,服务配置中心从远端读取配置文件,然后客户端服务再通过服务配置中心读取配置。
2. Config服务端配置与测试
1. 在GitHub上新建一个用作配置中心的新仓库,并克隆到本地开发硬盘目录
然后根据新建的Git地址,将GitHub上的仓库克隆岛本地
git clone https://github.com/Sher6J/springcloud-config.git
2. 新建Module:cloud-config-center-3344作为配置中心微服务
在其POM文件中引入服务配置中心的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
修改其配置文件application.yml如下:
server:
port: 3344
spring:
application:
name: cloud-config-center # 注册进Eureka服务器的微服务名
cloud:
config:
server:
git:
uri: https://github.com/Sher6J/springcloud-config.git # GitHub上面的git仓库名字
#### 搜索目录
search-paths:
- springcloud-config
#### 读取分支
label: master
#服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
然后编写主启动类,在主启动类上添加注解 @EnableConfigServer
使3344微服务具有配置中心功能:
package cn.sher6j.springcloud;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.config.server.EnableConfigServer;
/**
* @author sher6j
* @create 2020-05-23-9:56
*/
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class);
}
}
修改hosts文件,增加映射,使本机模拟网址服务配置中心网址:
127.0.0.1 config-3344.com
所以现在我们hosts文件开启了三个配置,分别是之前配置的Eureka服务注册中心集群和现在配置的服务配置中心:
3. 在GitHub上的服务配置中心仓库中建立配置文件
如图,就是创建了一个简单的配置文件,用来测试能否通过配置中心微服务获取内容。
4. 测试通过服务配置中心微服务3344是否可以从GitHub上获取配置内容
先启动Eureka服务注册中心,然后启动服务配置中心微服务3344,访问 http://config-3344.com:3344/master/config-dev.yml ,我们可以看到3344微服务可以成功的读取到远端的配置文件。
所以现在,服务配置中心从远端Git仓库读取配置文件这一部分已经搭建完成:
3. Config客户端配置与测试
1. 新建Module:cloud-config-client-3355作为访问配置中心的客户端
在其POM文件中引入Config配置中心客户端的启动类:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
编写配置文件bootstrap.yml:
application.yml是用户级的资源配置项,而bootstrap.yml是系统级的资源配置项,bootstrap.yml的优先级更高,SpringCloud会创建一个"Bootstrap Context",作为Spring应用的“Application Context"的父上下文。初始化的时候,“Bootstrap Context"负责从外部源加载配置属性并解析配置,这两个上下文共享一个从外部获取的"Environment”。”Bootstrap“属性有高优先级,默认情况系,它们不会被本地配置覆盖。"Bootstrap Context"和"Application Context"这两个上下文有不同的约定,所以新增一个bootstrap.yml文件,保证这两个上下文的配置分离。编写bootstrap配置文件如下:
server:
port: 3355
spring:
application:
name: config-client
cloud:
#Config客户端配置
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上述3个综合:master分支上config-dev.yml的配置文件被读取http://config-3344.com:3344/master/config-dev.yml
uri: http://localhost:3344 #配置中心地址k
#服务注册到eureka地址
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
然后老规矩,编写3355服务的主启动类,之后编写其业务类:
package cn.sher6j.springcloud.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author sher6j
* @create 2020-05-23-11:27
*/
@RestController
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
2. 测试客户端是否能够通过访问配置中心获取配置信息
按顺序启动Eureka服务注册中心、Config服务配置中心后,启动我们的服务配置中心客户端3355进行测试:
3. 存在的问题
我们在GitHub上修改配置文件内容,刷新3344配置中心服务端,发现Config Server配置中心立刻响应并刷新了配置信息,但是!!我们刷新3355客户端Config Client,发现没有任何响应,配置信息仍然是原来的配置信息。
难道每次远端修改了配置文件后,客户端都需要重启来进行对配置信息的重新加载吗?
4. Config客户端的动态刷新
为了避免每次远端更新配置信息都需要重启客户端微服务3355来加载更新的配置信息,我们需要使用动态刷新:
1. 修改3355模块,在POM中引入actuator监控:
其实actuator依赖几乎处了是网关的微服务外都得加。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2. 修改配置文件,暴露监控端口:
在bootstrap.yml中加入如下配置暴露监控断点:
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
3. @RefreshScope
注解
在业务类Controller上添加@RefreshScope
注解使客户端服务具有刷新功能:
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
4. 发送POST请求刷新客户端3355
该刷新请求必须发送后,客户端才能获得刷新后的信息,刷新客户端的请求必须是POST请求:
curl -X POST "http://127.0.0.1:3355/actuator/refresh"
当出现以上信息时激活刷新客户端3355成功,再次访问客户端,发现已经可以得到刷新后的配置信息。
但是假设如果我们有多个微服务客户端呢?难道每个微服务都需要执行一次POST请求进行手动刷新吗?事实上我们可以通过广播的方式进行一次通知,处处生效,这里就要学习消息总线——SpringCloud Bus。