请先阅读之前的内容:
Spring Cloud Config 介绍
https://cloud.spring.io/spring-cloud-config/
Spring Cloud Config provides server and client-side support for externalized configuration in a distributed system.
Spring Cloud Config 是 Spring Cloud 团队创建的一个全新项目,用来为分布式系统中的基础设施和微服务应用提供集中化的和可扩展的外部配置支持。
它分为服务端与客户端两个部分:
- 服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置仓库(例如 Git)并为客户端提供获取配置信息、加密/解密信息等访问接口
- 客户端则是微服务架构中的各个微服务应用或基础设施,它们通过指定的配置中心来管理应用资源与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息。
Spring Cloud Config 实现了对服务端和客户端中环境变量 Environment
和属性配置 PropertySource
的抽象映射,所以它除了适用于Spring 构建的应用程序之外,也可以在任何其他语言运行的应用程序中使用。
由于 Spring Cloud Config 实现的配置中心默认采用 Git 来存储配置信息,所以使用 Spring Cloud Config构建的配置服务器,天然就支持对微服务应用配置信息的版本管理,并且可以通过 Git 客户端工具来方便的管理和访问配置内容。当然它也提供了对其他存储方式的支持,比如:SVN仓库、本地化文件系统。
一个分布式配置的场景
场景描述:我们有一个服务,部署在分布式的环境上,服务需要访问数据库。通常情况下,我们将数据库的配置(例如数据库地址,用户名,密码等等)以文件的形式放置在项目自身的目录中。
这样的问题是,假如配置发生了变化(例如数据库用户名改变了),我们需要修改配置文件,重新 Build,重新 Deploy。
现在我们尝试将配置文件放在第三方的位置,例如 Git。然后我们创建一个配置中心 config-server
,它负责去 Git 仓库里读取文件内容。最后其他应用程序,例如之前创建的 eureka-consumer
通过配置中心 config-server
去读取配置。
在这里有一个问题,我们只创建了一个配置中心 config-server
,这样的话,会出现单点失败,并且负载均衡得不到保障。
因此我们需要创建多个配置中心,即分布式配置中心,每一个 config-server
都会以服务的形式注册到之前创建的服务注册中心 eureka-server
中去。
结构如下:该图引用自 https://blog.csdn.net/fox9916/article/details/79499854/
首先我们在 Github 上创建一个 repo,位置:https://github.com/chenxiangcyr/spring-cloud-config-repo-demo。可以看到,包括三个不同环境的配置文件(开发,测试,生产):
其中一个文件的内容如下 demo-dev.properties
:
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306
jdbc.username=rootDev
jdbc.password=rootDev
config-server 配置中心
通过的 Spring Assistant 插件来创建项目,具体过程不再赘述。
在 pom.xml
中导入了如下的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
随后在启动程序中通过 @EnableConfigServer
来开启 Spring Cloud Config 的服务端功能。:
@SpringBootApplication
@EnableConfigServer
@EnableDiscoveryClient
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
随后在 application.properties
中添加配置服务的基本信息以及 Git 仓库的相关信息。
spring.application.name=config-server
server.port=4001
# 服务注册中心
eureka.client.serviceUrl.defaultZone=http://localhost:1234/eureka/
# Git仓库地址
spring.cloud.config.server.git.uri=https://github.com/chenxiangcyr/spring-cloud-config-repo-demo/
# 如果我们的Git仓库需要权限访问,那么可以通过配置下面的两个属性来实现
# spring.cloud.config.server.git.username=
# spring.cloud.config.server.git.password=
# 配置文件所在的目录
spring.cloud.config.server.git.search-paths=/**
# 配置文件所在的分支
spring.cloud.config.label=master
management.endpoints.web.exposure.include=*
最后我们分别以 4001 和 4002 两个端口来启动 config-server
配置中心,可以看到每一个 config-server
都会以服务的形式注册到之前创建的服务注册中心 eureka-server
中去,点击 http://127.0.0.1:1234/ 查看如下:
随后我们就可以通过浏览器等工具直接来访问到我们的配置内容了。访问配置信息的 URL 与配置文件的映射关系如下:
/{application}/{profile}/{label}
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
上面的 URL 会映射{application}-{profile}.properties
对应的配置文件,其中 {label}
对应Git上不同的分支,默认为 master
。
例如我们通过 http://127.0.0.1:4001/demo/dev/ 的形式读取配置文件的具体内容:
{
name: "demo",
profiles: [
"dev"
],
label: null,
version: "92f9ab1bff77011b8ab16f0d2dc7e3f24e326f6d",
state: null,
propertySources: [
{
name: "https://github.com/chenxiangcyr/spring-cloud-config-repo-demo//demo-dev.properties",
source: {
jdbc.driverClassName: "com.mysql.jdbc.Driver",
jdbc.url: "jdbc:mysql://127.0.0.1:3306",
jdbc.username: "rootDev",
jdbc.password: "rootDev"
}
}
]
}
获取配置信息
在这里,我们利用之前创建的项目 eureka-consumer
,使得它可以通过分布式配置中心 config-server
来读取配置。
首先在 pom.xml
中添加了如下的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
随后创建 bootstrap.properties
,用来配置配置中心:
# 开启配置服务发现
spring.cloud.config.enabled=true
# 配置服务实例名称
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.service-id=config-server
spring.cloud.config.name=demo
spring.cloud.config.profile=dev
spring.cloud.config.label=master
eureka.client.serviceUrl.defaultZone=http://localhost:1234/eureka/
注意:上面这些属性必须配置在 bootstrap.properties
中,这样 config-server
中的配置信息才能被正确加载。
随后,我们创建一个新的 ReadConfigController
来通过 @Value
注解的形式读取配置:
@RestController
public class ReadConfigController {
private final static Logger logger = LoggerFactory.getLogger(ReadConfigController.class);
@Value("${jdbc.driverClassName}")
String driverClassName;
@Value("${jdbc.url}")
String url;
@Value("${jdbc.username}")
String username;
@Value("${jdbc.password}")
String password;
@GetMapping("/config")
public String config() {
logger.info("jdbc.driverClassName = " + driverClassName);
logger.info("jdbc.url = " + url);
logger.info("jdbc.username = " + username);
logger.info("jdbc.password = " + password);
return "success";
}
}
最后,重启 eureka-consumer
,访问新创建的 Rest 接口 http://127.0.0.1:3001/config,可以在日志中看到,配置被成功读取:
推送通知和 Spring Cloud Bus
在上面的示例中,有一个问题:我们通过 Git 修改来 demo-dev.properties
文件中的内容,但是更新后的内容并没有被 eureka-consumer
获取到。
现在我们来解决这个问题:
许多源代码存储库提供程序(例如Github,Gitlab 或 Bitbucket)将通过 Webhook 通知您存储库中的更改。
可以通过提供商的用户界面将 Webhook 配置为 URL 和一组感兴趣的事件,例如:
流程如下图所示:引用自 https://blog.csdn.net/mazhen1991/article/details/78513452
对于配置中心 config-server
,需要进行如下修改
添加如下的依赖到 pom.xml
中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-monitor</artifactId>
</dependency>
安装并启动一个 RabbitMQ 实例,并在 application.properties
中配置 RabbitMQ 连接信息:
spring.rabbitmq.host=127.0.0.1
对于 eureka-consumer
,需要进行如下修改
添加如下的依赖到 pom.xml
中:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
在 application.properties
中配置 RabbitMQ 连接信息:
spring.rabbitmq.host=127.0.0.1
拓展阅读
引用:
程序猿DD Spring Cloud基础教程
Spring Cloud构建微服务架构:分布式配置中心【Dalston版】
Spring Cloud Dalston中文文档