文章目录
1、概述
①、问题出现
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息才能运行,所以一套集中式的、动态的配置管理设施是必不可少的。
回顾我们以前创建的微服务,每一个
module
都有一个对应的application.yml
文件,单拎出来服务提供者这几个module
,如果每一个都用到了mybatis
,且操作的都是同一个数据库,但是我们在每一个module
都进行了一遍相同的数据库连接配置,这样的操作实在麻烦,如果我们没有一个统一的配置中心,当我们对数据库进行某些必要的修改后,我们就需要修改每一个module
的配置,何其麻烦。再比如我们在开发的时候要使用一套开发环境,测试一套环境,上线又是一套环境,那微服务越来越多,修改起来难度是不是就越来越大啊。所以对于服务配置中心出现,是很有必要的。
②、是什么配置中心
SpringCloud Config
为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。分为服务端和客户端两部分组成。
- 服务端又称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访问接口
- 客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用
git
来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git
客户端工具来方便的管理和访问配置内容
③、能干什么
- 集中管理配置文件
- 不同环境不同配置,动态的配置更新,分环境部署如
dev/test/prod/beta/release
- 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
- 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置
- 将配置信息以
REST
接口的形式暴露 - 与
Github
整合:由于SpringcloudConfig
默认使用Git
来存储配置文件(也有其他方式,比如支持SVN
和本地文件),但最推荐的是Git
,而且使用http/https
访问的形式
2、服务端配置与测试
①、新建一个Git仓库
②、克隆到本地
这一步仅仅是为了方便自己本地修改仓库信息,与项目配置无关
③、创建配置文件
推送到远程
④、新建module
⑤、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>SpringCloudDemo</artifactId>
<groupId>com.phz.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ConfigCenter3344</artifactId>
<dependencies>
<!--config server-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>com.phz.springcloud</groupId>
<artifactId>CloudAPI</artifactId>
<version>1.0-SNAPSHOT</version>
</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>
<!--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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
⑥、YML
server:
port: 3344
spring:
application:
name: config-center
cloud:
config:
server:
git:
uri: https://github.com/PengHuAnZhi/CloudDemoConfig #Github上的git仓库地址
##搜索目录.这个目录指的是github上的目录
search-paths:
- CloudDemoConfig
##读取分支
label: main
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
⑦、主启动
/**
* @author PengHuAnZhi
* @createTime 2021/2/16 12:00
* @projectName SpringCloudDemo
* @className ConfigCenterMain3344.java
* @description TODO
*/
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class, args);
}
}
⑧、配置hosts
添加
config-3344.com
映射127.0.0.1
,路径为C:\Windows\System32\drivers\etc\hosts
###########SpringCloudConfigCenter###########
127.0.0.1 config3344.com
⑨、测试
通过
ConfigCenter
查看config-dev
配置文件
http://config3344.com:3344/main/config-dev.yml
修改
config-dev
配置文件,再次访问
3、客户端配置与测试
①、新建module
②、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>SpringCloudDemo</artifactId>
<groupId>com.phz.springcloud</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>ConfigClient3355</artifactId>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>com.phz.springcloud</groupId>
<artifactId>CloudAPI</artifactId>
<version>1.0-SNAPSHOT</version>
</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>
<!--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-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
③、YML
强调这个时候的
yml
配置文件需要命名为bootstrap
,不再是application
,applicaiton.yml
是用户级的资源配置项bootstrap . yml
是系统级的,优先级更加高。Bootstrap
)属性有高优先级,默认情况下,它们不会被本地配置覆盖。Bootstrap context
和Application Context
有着不同的约定,所以新增了一个bootstrap.yml
文件,保证Bootstrap Context
和Application Context
配置的分离。
Spring Cloud
会创建一个“Bootstrap Context”
,作为Spring
应用的Application Context
的父上下文。初始化的时候,BootstrapContext
负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的``Environment’,换句话说就是分布式微服务种,我一个服务带着两份配置文件,一个
bootstrap负责和总配置中心的沟通的,
application是仅跟自己沟通的配置文件,也就是先加载
bootstrap再加载
application`,前者优先级更高
server:
port: 3355
spring:
application:
name: config-client
cloud:
#Config客户端配置
config:
label: master #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上诉3个综合就是 master分支上 config-dev.yml
uri: http://localhost:3344
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
④、主启动
/**
* @author PengHuAnZhi
* @createTime 2021/2/16 15:27
* @projectName SpringCloudDemo
* @className ConfigClientMain3355.java
* @description TODO
*/
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class, args);
}
}
⑤、Controller
/**
* @author PengHuAnZhi
* @createTime 2021/2/16 15:30
* @projectName SpringCloudDemo
* @className ConfigClientController.java
* @description TODO
*/
@RestController
@Slf4j
public class ConfigClientController {
// 因为config仓库以rest形式暴露,所以所有客户端都可以通过config服务端访问到github上对应的文件信息
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
⑥、测试
4、客户端动态刷新
①、问题出现
修改远程仓库的
dev
配置文件
再次访问
3344
,发现能够实时更新
访问
3355
,可以发现客户端无论刷新多少次version
都是1
,当重新启动后,才更新。这对于微服务来说可是噩梦,有些微服务启动一次花费的时间是十分巨大的。
为了避免每次修改配置都需要重启服务,接下来开始配置动态刷新
②、添加POM依赖
前面
POM
已经添加了,这里是要强调一下,这个jar
包是必须的
<!--监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
③、修改YML
server:
port: 3355
spring:
application:
name: config-client
cloud:
#Config客户端配置
config:
label: main #分支名称
name: config #配置文件名称
profile: dev #读取后缀名称 上诉3个综合就是 master分支上 config-dev.yml
uri: http://localhost:3344
eureka:
client:
service-url:
defaultZone: http://eureka7001.com:7001/eureka/
#暴露监控端点
management:
endpoints:
web:
exposure:
include: "*"
④、添加注解
在
Controller
上面添加一个@RefreshScope
注解
/**
* @author PengHuAnZhi
* @createTime 2021/2/16 15:30
* @projectName SpringCloudDemo
* @className ConfigClientController.java
* @description TODO
*/
@RestController
@Slf4j
@RefreshScope
public class ConfigClientController {
// 因为config仓库以rest形式暴露,所以所有客户端都可以通过config服务端访问到github上对应的文件信息
@Value("${config.info}")
private String configInfo;
@GetMapping("/configInfo")
public String getConfigInfo() {
return configInfo;
}
}
⑤、测试
修改远程仓库,
version
改为4
访问
3344
访问
3355
,哈哈哈哈,怎么还是3
⑥、手动发送POST请求刷新
还有一步,需要做运维的大哥手动发送一个POST请求给
3355
来刷新
curl -X POST "http://localhost:3355/actuator/refresh"
⑦、再次测试
此时我并没有重启3355,再次访问测试一下可不可以更新配置
6、新的问题
我:大哥你改完发个
POST
请求刷新一下运维攻城狮:我不,你们那么多微服务,难道要我一个个全部发个
POST
?我:我们重启微服务很费资源和时间啊,大哥好商量。
运维攻城狮:我
TM
不干了!
如果微服务过多,修改一次配置就需要每个微服务都发送
POST
请求刷新一次,这样真的好吗?能否找到类似于广播,一次刷新,处处生效?可以考虑下面的解决方法:
- 写个for循环
- 写个自动化脚本,自动执行
但是如果在运行的服务中,假设共有
100
台,其中有2
台因为版本的问题,暂时不需要跟新配置,我们又如何进行精确刷新呢?这就引入了新的组件Bus消息总线