此文章主要讲解springcloud中的分布式配置中心Config(不推荐)的相关知识,一般和SpringCloud Bus一同使用,绝代双骄。
什么是配置中心
配置中心概述
-
对于传统的单体应用而言,常使用配置文件来管理所有配置,比如SpringBoot的
application.yml
文件,但是在微服务架构中全部手动修改
的话很麻烦而且不易维护。 -
微服务的配置管理一般有以下需求:
-
- 集中配置管理,一个微服务架构中可能有成百上千个微服务,所以
集中配置管理
很重要。
- 集中配置管理,一个微服务架构中可能有成百上千个微服务,所以
-
- 不同环境不同配置:比如数据源配置在不同环境(开发、测试、生产)中是不同的。
-
- 运行期间可动态调整。比如可以根据各个微服务的负载情况,动态调整数据源连接池的大小等。
-
- 配置修改后可以自动更新。比如配置内容发生改变,微服务可以自动更新配置。
-
综上所述,对于微服务架构来说,一套统一的、通用的管理配置机制是不可缺少的重要组成部分。常见的做法就是通过配置服务器进行管理。
常见的配置中心
Spring Cloud Config
- Spring Cloud Config是分布式系统中的外部配置提供服务器和客户端支持。
Apollo(阿波罗)
- Apollo(阿波罗)是携程框架部门研发的分布式配置中心,能够集中化管理应用不同环境、不同集群的配置,配置修改后能够实时推送到应用端,并且具备规范的权限、流程治理等特性,适用于微服务配置管理场景。
Nacos
-
Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。
-
Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。 Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。
Spring Cloud Config
简介
Spring Cloud Config项目是一个解决分布式系统的配置解决方案。
它包含了Client和Server两个部分,Server提供配置文件的存储,以接口的形式将配置文件的内容提供出去;Client通过接口获取数据,并依据此数据初始化自己的应用。
-
Spring Cloud Config为分布式系统的外部配置提供服务器和客户端支持。使用Config Server,您可以为所有环境中的应用程序管理其外部属性。它非常适合Spring应用,也可以使用在其他语言的应用上。随着应用程序通过从开发到测试和生产的部署流程,您可以管理这些环境之间的配置,并确定应用程序具有迁移时需要运行的一切。服务器存储后端的默认
使用Git
,因此他轻松的支持标签版本的配置环境以及可以访问用于管理内容的各种工具。 -
Spring Cloud Config服务端的特性:
-
- Http,为外部配置提供基于资源的API(键值对或者等价的YAML内容)。
-
- 属性值的加密和解密(对称加密和非对称加密)。
-
- 通过使用@EnableConfigServer在Spring Boot应用中非常简单的嵌入。
-
Spring Cloud Config客户端的特性:
-
- 绑定Config服务端,并使用远程的属性源初始化Spring环境。
-
- 属性值的加密和解密(对称加密和非对称加密)。
能干嘛?
入门案例
Git配置
首先在github
或者gitee
上新建一个仓库 springcloud-config
然后使用git命令克隆到本地,命令
git clone https://gitee.com/xiaojinggege/springcloud-config.git
注意上面的操作不是必须的,只要github或者gitee上有就可以,克隆到本地只是修改文件。
在本地新建多个环境的配置文件,添加一点内容:
config-dev.yml
config-prod.yml
config-test.yml
# 比如添加内容为,不同配置内容不一样,根据环境修改
config:
info: dev
保存格式必须为UTF-8
,然后将文件push到gitee上
git命令:
git add .
git commit -m "init yml"
git push origin master
搭建工程
服务端配置
新建模块
cloud-config-center3344
POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>spring_cloud_atguigu_2020</artifactId>
<groupId>com.itjing.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cloud-config-center3344</artifactId>
<dependencies>
<!-- config Server -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
YML文件
server:
port: 3344
spring:
application:
name: cloud-config-center # 注册进eureka Server 的微服务名
cloud:
config:
server:
git:
uri: https://gitee.com/xiaojinggege/springcloud-config.git # git 仓库位置
# 配置git的用户名
username:
# 配置git的密码
password:
# 搜索目录
search-paths:
- springcloud-config
# 读取的分支
label: master
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
主启动类
@SpringBootApplication
@EnableConfigServer //关键注解
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class,args);
}
}
添加映射
【C:\Windows\System32\drivers\etc\hosts】
文件中添加:
127.0.0.1 config-3344.com
测试
启动微服务3344
访问 http://config-3344.com:3344/master/config-dev.yml 文件,前提是gitee上有这个文件
文件命名和访问的规则
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml # 推荐方式
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
根据分支:
不加分支名默认是master。
客户端配置
这里的客户端指的是使用 Config Server 统一配置文件
的项目。
新建模块
cloud-config-client-3355
POM文件
<dependencies>
<!-- config Client 和 服务端的依赖不一样 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<!--eureka-client-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
配置bootstrap.yml
-
bootstrap.yml是
系统级别
的资源配置项,application.yml是用户级别
的资源配置项。 -
Spring Cloud会创建一个“Boostrap Context”,作为Spring应用的“Application Context”的父上下文。初始化的时候,“Boostrap Context”负载从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的“Environment”。
-
“Boostrap”属性有高优先级,默认情况下,不会覆盖本地配置项。“Bootstrap Context”和“Application Context”有着不同的约定,所以新增了一个“bootstrap.yml”,保证“BootStrap Context”和“Application Context”配置的分离。
-
要将Client模块下的application.yml改为bootstrap.yml
,很关键。因为bootstrap.yml比application.yml优先加载。bootstrap.yml优先级高于application.yml
。
server:
port: 3355
spring:
application:
name: config-client
cloud:
# config 客户端配置
config:
label: master # 分支名称
name: config # 应用名称,需要对应git中配置文件名称的前半部分
profile: dev # 开发环境,需要对应git中配置文件名称的后半部分
uri: http://config-3344.com:3344 # config Server 的请求地址
# 综合上面四个 即读取配置文件地址为: http://config-3344.com:3344/master/config-dev.yml
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
主启动类
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class, args);
}
}
Controller
用来测试读取配置信息
@RestController
@Slf4j
public class ConfigClientController {
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
测试
访问: http://localhost:3355/configInfo ,这样就可以获取到信息。
手动刷新
出现问题
也就是github上面配置更新了,config Server 项目上是动态更新的,但是,client端的项目中的配置,目前还是之前的,读取的是缓存,它不能动态更新,必须重启才行。
概述
我们已经在客户端获取到了配置中心的值,但是当我们修改git中的值的时候,服务端(Config Server)能实时的获取到最新的值,但是客户端(Config Client)读取的是缓存,无法实时获取最新值
。SpringCloud已经为我们解决了这个问题,那就是客户端使用POST去触发refresh,获取最新数据,需要依赖spring-boot-starter-actuator
。
解决
1、client端一定要有如下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2、client 端增加 yml 配置如下,即在 bootstrap.yml 文件中增加如下内容:
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
3、在Controller 上添加注解 @RefreshScope
开启动态刷新。
测试
在Git服务器上修改配置之后,需要使用curl -X POST "http://localhost:3355/actuator/refresh"
向客户端发送一个POST请求。
两个必须:
- 必须是 POST 请求
- 请求地址:http://localhost:3355/actuator/refresh
其他问题
假如有多个微服务客户端,每个微服务都要执行一次POST请求手动刷新?
可否广播,一次通知,处处生效?
当微服务数量庞大,又是一个新的问题。
这样就引入了后面的消息总线Bus
!
配置中心的高可用
概述
-
在之前的代码中,客户端都是直接调用配置中心的Server端来获取配置信息。这样就存在了一个问题,客户端和服务端的耦合性太高,如果Server要做集群,客户端只能通过原始的方式来路由,Server端改变IP地址的时候,客户端也需要修改配置,不符合Spring Cloud 服务治理的概念。
-
Spring Cloud提供了这样的解决方案,我们只需要将Server端当做一个服务注册到Eureka中,Client端去Eureka中去获取配置中心Server端的服务即可。
服务端改造
1、导入Eureka Client的依赖
<!-- 导入Eureka Client对应的坐标 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2、application.yml
server:
port: 3344
spring:
application:
name: config-server
cloud:
config:
server:
git:
# git服务地址
uri: https://gitee.com/xiaojinggege/springcloud-config.git
# 配置git的用户名
username:
# 配置git的密码
password:
search-paths:
- springcloud-config
# 分支
label: master
# 配置 eureka
eureka:
instance:
# 主机名称:其实就是向eureka server中注册的实例id
instance-id: config-server:${server.port}
# 显示IP信息
prefer-ip-address: true
client:
service-url: # 此处修改为 Eureka Server的集群地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
客户端改造
1、bootstrap.yml
spring:
application:
name: config-client
cloud:
config:
name: config # 应用名称,需要对应git中配置文件名称的前半部分
profile: dev # 开发环境,需要对应git中配置文件名称的后半部分
label: master # 分支名称
# uri: http://config-3344.com:3344 # config-server的请求地址
discovery: # 服务发现
service-id: config-server
enabled: true # 从Eureka中获取配置信息
# 配置 eureka
eureka:
instance:
# 主机名称:其实就是向eureka server中注册的实例id,自己根据情况修改
instance-id: service-payment-dev:${server.port}
# 显示IP信息
prefer-ip-address: true
client:
service-url: # 此处修改为 Eureka Server的集群地址
defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
# 暴露监控端点
management:
endpoints:
web:
exposure:
include: '*'