概述
分布式系统面临的问题
微服务意味着要将单体应用中的业务拆分成一个个子服务,每个服务的粒度相对较小,因此系统中会出现大量的服务。由于每个服务都需要必要的配置信息オ能运行,所以一套集中式的、动态的配置管理设施是必不可少的
Spring Cloud提供了 Config Server来解决这个问题,我们每一个微服务自己帯着一个 application. yml,上百个配置文件的管理….
是什么
Spring Cloud Config为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。
怎么玩
Spring Cloud Config分为服务端和客户端两部分。
服务端也称为分布式配置中心,它是一个独立的微服务应用,用来连接配置服务器并为客户端提供获取配置信息,加密/解密信息等访可接口
客户端则是通过指定的配置中心来管理应用资源,以及与业务相关的配置内容,并在启动的时候从配置中心获取和加载配置信息配置服务器默认采用git来存储配置信息,这样就有助于对环境配置进行版本管理,并且可以通过git客户端工具来方便的管理和访问配置内容
能干嘛
1. 集中管理配置文件
2. 不同环境不同配置,动态化的配置更新,分环境部署比如dev/test/prod/beta/release
3. 运行期间动态调整配置,不再需要在每个服务部署的机器上编写配置文件,服务会向配置中心统一拉取配置自己的信息
4. 当配置发生变动时,服务不需要重启即可感知到配置的变化并应用新的配置
5. 将配置信息以REST接口的形式暴露,post、curl访问刷新均可….
与GitHub整合配置
由于SpringCloud Config默认使用Git来存储配置文件(也有其它方式,比如支持svn和本地文件,但最推荐的还是Git,而且使用的是http/https访问的形式)
Config服务端配置与测试
创建仓库
用你自己的账号在Github上新建一个名为sprincloud-config的新Repository
由上一步获得刚新建的git地址,写你自己的仓库地址
本地硬盘上新建git仓库并clone
本地地址:E:\config
git命令:git clone xxx
此时在本地E盘符下E:\config\springcloud-config
表示多个环境的配置文件
保存格式必须为UTF-8
如果需要修改,此处模拟运维人员操作git和github
新建Module模块
新建Module模块cloud-config-center-3344它既为Cloud的配置中心模块cloudConfig
改pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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>
配置
server:
port: 3344
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: https://e.coding.net/gysuiyueran/config/springcloud-config.git # 填写你自己的git仓库路径
force-pull: true
username: 2782308186@qq.com
password: flzx3000C@)!&
search-paths:
- springcloud-config
# 分支
label: master
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# defaultZone: http://eureka7002.com:7002/eureka,http://eureka7001.com:7001/eureka/ #集群版
defaultZone: http://eureka7001.com:7001/eureka/
instance:
instance-id: cloud-config-center
prefer-ip-address: true #访问路径可以显示ip地址
# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
主启动类
@SpringBootApplication
@EnableConfigServer
public class ConfigCenterMain3344 {
public static void main(String[] args) {
SpringApplication.run(ConfigCenterMain3344.class,args);
}
}
windows下修改hosts文件,增加映射
127.0.0.1 config-center.com
测试
测试通过Config微服务是否可以从Github上获取配置内容
1. 启动微服务3344
2. http://config-center.com:3344/master/config-dev.yml
当我们启动3344微服务的时候,出现如下错误,这是ssl权限设置问题
Caused by: org.eclipse.jgit.errors.TransportException: https://e.coding.net/gysuiyueran/config/springcloud-config.git: Authentication is required but no CredentialsProvider has been registered
出错解决办法
springcloud config :Authentication is required but no CredentialsProvider has been registered
在注册中心配置git 仓库地址,那么我们需要配置git 用户名密码进行安全链接:
spring:
application:
name: cloud-config-center
cloud:
config:
server:
git:
uri: https://e.coding.net/gysuiyueran/config/springcloud-config.git # 填写你自己的git仓库路径
force-pull: true
username: 123124@qq.com
password: 1231
search-paths:
- springcloud-config
# 分支
label: master
问题解决接着测试
重启3344微服务
浏览器进行访问 ,http://config-center.com:3344/master/config-dev.yml
浏览器进行访问 ,http://config-center.com:3344/master/config-test.yml
浏览器进行访问 ,http://config-center.com:3344/master/config-prod.yml
配置读取规则
官网
/{label}/{application}-{profile}.yml(最推荐使用这种方式
master分支
1. http://config-center.com:3344/master/config-dev.yml
2. http://config-center.com:3344/master/config-test.yml
3. http://config-center.com:3344/master/config-prod.yml
dev分支
1. http://config-center.com:3344/dev/config-dev.yml
2. http://config-center.com:3344/dev/config-test.yml
3. http://config-center.com:3344/dev/config-prod.yml
/{application}-{profile}.yml
首先会找主分支,如果主分支没有再找其他分子
1. http://config-center.com:3344/config-dev.yml
2. http://config-center.com:3344/config-test.yml
3. http://config-center.com:3344/config-prod.yml
4. http://config-center.com:3344/config-xxxx.yml(不存在的配置)
/{application}-{profile}[/{label}]
http://config-center.com:3344/config/dev/master
http://config-center.com:3344/config/test/master
http://config-center.com:3344/config/prod/master
Config客户端配置与测试
新建cloud-config-client-3355
新建cloud-config-client-3355
pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>false</optional>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<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-actuator</artifactId>
</dependency>
bootstap.yml
是什么
applicaiton.yml是用户级的资源配置项
bootstrap.yml是系统级的,优先级更加高
Spring Cloud会创建一个” Bootstrap Context”,作为 Spring应用的 Application Contextt的父上下文。初始化的时候, Bootstrap Context负责从外部源加载配置属性并解析配置。这两个上下文共享一个从外部获取的 Environment。
Bootstrap属性有高优先級,默认情況下,它们不会被本地配置覆盖。 Bootstrap context’和 Application Context有着不同的约定,所以新増了一个 bootstrap yml文件,保证 Bootstrap Context和 Application Context配置的分离。
要将 Client模块下的 application yml文件改为 bootstrap.yml,这是很关健的
因为 bootstrap yml是比 application. yml先加载的。 bootstrap ym优先级高于 application. yml
server:
port: 3355
spring:
application:
name: config-client
cloud:
config:
label: master # 分支名字
name: config # 配置文件名称
profile: dev # 读取后缀名称
uri: http://localhost:3344 #上述三个综合,master分支上的config-dev.yml的配置文件被读取 http://localhost:3344/master/config-dev.yml
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# defaultZone: http://eureka7002.com:7002/eureka,http://eureka7001.com:7001/eureka/ #集群版
defaultZone: http://eureka7001.com:7001/eureka/
instance:
instance-id: cloud-config-client
prefer-ip-address: true #访问路径可以显示ip地址
# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
主启动类
ConfigClientMain3355
@SpringBootApplication
@EnableEurekaClient
public class ConfigClientMain3355 {
public static void main(String[] args) {
SpringApplication.run(ConfigClientMain3355.class,args);
}
}
业务类
@RestController
public class ConfigClientController {
@Value("${config.name}")
private String configName;
@GetMapping("/configName")
public String getConfigName(){
return configName;
}
}
测试
修改config-dev.yml配置并提交到GitHub中,比如加个变量age或者版本号version
启动Config配置中心3344微服务并自测,http://config-center.com:3344/master/config-dev.yml
启动3355作为Client准备访问,http://localhost:3355/configName
成功实现了客户端3355访问SpringCloud Config3344通过GitHub获取配置信息
问题随时而来,分布式配置的动态刷新
Linux运维修改GitHub上的配置文件内容做调整
刷新3344,发现ConfigServer配置中心立刻响应
刷新3355,发现ConfigServer客户端没有任何响应
3355没有变化除非自己重启或者重新加载
难道每次运维修改配置文件,客户端都需要重启??噩梦
Config客户端动态刷新
避免每次更新配置都要重启客户端微服务3355
步骤
POM引入actuator监控
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
修改YML,暴露监控端口
server:
port: 3355
spring:
application:
name: config-client
cloud:
config:
label: master # 分支名字
name: config # 配置文件名称
profile: dev # 读取后缀名称
uri: http://localhost:3344 #上述三个综合,master分支上的config-dev.yml的配置文件被读取 http://localhost:3344/master/config-dev.yml
eureka:
client:
register-with-eureka: true
fetch-registry: true
service-url:
# defaultZone: http://eureka7002.com:7002/eureka,http://eureka7001.com:7001/eureka/ #集群版
defaultZone: http://eureka7001.com:7001/eureka/
instance:
instance-id: cloud-config-client
prefer-ip-address: true #访问路径可以显示ip地址
# Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒)
lease-renewal-interval-in-seconds: 1
#Eureka服务端在收到最后一次心跳后等待时间上限,单位为秒(默认是90秒),超时将剔除服务
lease-expiration-duration-in-seconds: 2
management:
endpoints:
web:
exposure:
include: "*"
业务类Controller修改
添加 @RefreshScope
自动刷新注解
@RestController
@RefreshScope
public class ConfigClientController {
@Value("${config.name}")
private String configName;
@GetMapping("/configName")
public String getConfigName(){
return configName;
}
}
测试一下
此时修改github—-> 3344 —-> 3355
使用浏览器访问 http://localhost:3355/configName,结果发现依旧没有改变
需要运维人员发送Post请求刷新3355
必须是Post请求
curl命令如下
curl -X POST "http://localhost:3355/actuator/refresh"
再次测试一下
访问 http://localhost:3355/configName,发现改变了
成功实现了客户端3355刷新到最新配置内容:避免了服务的重启
想想还有什么问题?
假如有多个微服务客户端3355/3366/3377。。。。
每个微服务都要执行一次post请求,手动刷新?
可否广播,一次通知,处处生效?
我们想大范围的自动刷新,求方法
这就引出了总线概念