一、概述
二、Config
三、Refresh
四、配置中心服务化
五、基于Webhook和消息总线的解决方案
一、概述
SpringCloud配置中心包括Config和Bus两个组成部分,只要这样,才能保证主动推送。
下面主要分为四个部分,
Config讲了基本的配置中心,但这样如果修改配置客户端在运行中是无法改变的。
Refresh讲了我们修改配置文件后可以向客户端发送一个POST请求,可以利用WebHook的方式。
配置中心服务化讲了我们把配置中心独立成一个服务(最好多挂几个)挂到Eureka
基于Webhook和消息总线的解决方案,让我们客户端可以实时的感知配置变化,从而做出改边。
我们先看Config,然后集成Bus来达到我们配置中心的目的。
二、Config
1.Config概述
当一个系统配置文件修改,我们需要重启系统,但是微服务状态下系统数量太多,为了方便服务配置文件统一管理,实时更新,所以需要分布式配置中心组件。在Spring Cloud中,有分布式配置中心组件spring cloud config ,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中。在spring cloud config 组件中,分两个角色,一是config server,二是config client。
引入spring cloud config后,我们的外部配置文件就可以集中放置在一个git仓库里,再新建一个config server,用来管理所有的配置文件,维护的时候需要更改配置时,只需要在本地更改后,推送到远程仓库,所有的服务实例都可以通过config server来获取配置文件,这时每个服务实例就相当于配置服务的客户端config client,为了保证系统的稳定,配置服务端config server可以进行集群部署,即使某一个实例,因为某种原因不能提供服务,也还有其他的实例保证服务的继续进行。
2.示例
⑴server
①添加依赖
org.springframework.cloud
spring-cloud-config-server
②配置文件
server:
port: 8001
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/cGitHub123/Springcloud.git # 配置git仓库的地址
search-paths: config-repo # git仓库地址下的相对地址,可以配置多个,用,分割。
username: # git仓库的账号
password: # git仓库的密码
Spring Cloud Config也提供本地存储配置的方式。我们只需要设置属性spring.profiles.active=native,Config Server会默认从应用的src/main/resource目录下检索配置文件。也可以通过spring.cloud.config.server.native.searchLocations=file:E:/properties/属性来指定配置文件的位置。虽然Spring Cloud Config提供了这样的功能,但是为了支持更好的管理内容和版本控制的功能,还是推荐使用git的方式。
③启动类
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
④测试
直接访问:http://localhost:8001/neo-config/dev
返回值:
{
"name": "neo-config",
"profiles": [
"dev"
],
"label": null,
"version": null,
"state": null,
"propertySources": [
{
"name": "https://github.com/cGitHub123/Springcloud.git/config-repo/neo-config-dev.properties",
"source": {
"neo.hello": "hello im dev update"
}
}
]
}
上述的返回的信息包含了配置文件的位置、版本、配置文件的名称以及配置文件中的具体内容,说明server端已经成功获取了git仓库的配置信息。
如果直接查看配置文件中的配置信息可访问:http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev
修改配置文件neo-config-dev.properties中配置信息为:neo.hello=hello im dev update,再次在浏览器访问http://localhost:8001/neo-config-dev.properties,返回:neo.hello: hello im dev update。说明server端会自动读取最新提交的内容
仓库中的配置文件会被转换成web接口,访问可以参照以下的规则:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
以neo-config-dev.properties为例子,它的application是neo-config,profile是dev。client会根据填写的参数来选择读取对应的配置。
⑵Client端
①添加依赖
org.springframework.cloud
spring-cloud-starter-config
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-test
test
②配置文件
需要配置两个配置文件,application.properties和bootstrap.properties
application.properties如下:
spring.application.name=spring-cloud-config-client
server.port=8002
bootstrap.properties如下:
spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.uri=http://localhost:8001/
spring.cloud.config.label=master
spring.application.name:对应{application}部分
spring.cloud.config.profile:对应{profile}部分
spring.cloud.config.label:对应git的分支。如果配置中心使用的是本地存储,则该参数无用
spring.cloud.config.uri:配置中心的具体地址
spring.cloud.config.discovery.service-id:指定配置中心的service-id,便于扩展为高可用配置集群。
特别注意:上面这些与spring-cloud相关的属性必须配置在bootstrap.properties中,config部分内容才能被正确加载。因为config的相关配置会先于application.properties,而bootstrap.properties的加载也是先于application.properties。
③启动类
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
④Web测试
使用@Value注解来获取server端参数的值
@RestController
class HelloController {
@Value("${neo.hello}")
private String hello;
@RequestMapping("/hello")
public String from() {
return this.hello;
}
}
启动项目后访问:http://localhost:8002/hello,返回:hello im dev update说明已经正确的从server端获取到了参数。到此一个完整的服务端提供配置服务,客户端获取配置参数的例子就完成了。
我们在进行一些小实验,手动修改neo-config-dev.properties中配置信息为:neo.hello=hello im dev update1提交到github,再次在浏览器访问http://localhost:8002/hello,返回:neo.hello: hello im dev update,说明获取的信息还是旧的参数,这是为什么呢?因为springboot项目只有在启动的时候才会获取配置文件的值,修改github信息后,client端并没有在次去获取,所以导致这个问题。如何去解决这个问题呢?
三、Refresh
为了解决上面的问题,我们修改Client端,我们一修改配置,就给客户端发个POST请求,我们不但要解决上面问题,还要让客户端主动感知提交的代码从而主动的更新:
1.添加依赖
org.springframework.boot
spring-boot-starter-actuator
spring-boot-starter-actuator是一套监控的功能,可以监控程序在运行时状态,其中就包括/refresh的功能。
2.开启更新机制
需要给加载变量的类上面加载@RefreshScope,在客户端执行/refresh的时候就会更新此类下面的变量值。
@RestController
@RefreshScope // 使用该注解的类,会在接到SpringCloud配置中心配置刷新的时候,自动将新的配置更新到该类对应的字段中。
class HelloController {
@Value("${neo.hello}")
private String hello;
@RequestMapping("/hello")
public String from() {
return this.hello;
}
}
在这种模式下,我们先请求服务端
http://localhost:8001/neo-config-dev.properties
返回:
neo.hello: hello im dev update
然后我们请求客户端
http://localhost:8002/hello
返回:
hello im dev update bus
我们手动修改配置文件,请求服务端:
neo.hello: hello im dev update bus edit
这时候我们手动执行:
curl -X POST http://localhost:8002/bus/refresh
请求客户端:
neo.hello: hello im dev update bus edit
四、配置中心服务化
1.服务端改造
⑴添加依赖
org.springframework.cloud
spring-cloud-config-server
org.springframework.cloud
spring-cloud-starter-eureka
⑵配置文件
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 注册中心eurka地址
⑶启动类
启动类添加@EnableDiscoveryClient激活对配置中心的支持
@EnableDiscoveryClient
@EnableConfigServer
@SpringBootApplication
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
然后我们启动一个Eureka服务,再启动上面的启动类,可以看到已经注册上去了,这里我们可以将服务端改为高可用模式
2.客户端改造
⑴添加依赖
org.springframework.cloud
spring-cloud-starter-config
org.springframework.boot
spring-boot-starter-web
org.springframework.cloud
spring-cloud-starter-eureka
org.springframework.boot
spring-boot-starter-test
test
⑵配置文件
spring.application.name=spring-cloud-config-client
server.port=8002
spring.cloud.config.name=neo-config
spring.cloud.config.profile=dev
spring.cloud.config.label=master
spring.cloud.config.discovery.enabled=true
spring.cloud.config.discovery.serviceId=spring-cloud-config-server
eureka.client.serviceUrl.defaultZone=http://localhost:8000/eureka/
主要是去掉了spring.cloud.config.uri直接指向server端地址的配置,增加了最后的三个配置:
spring.cloud.config.discovery.enabled :开启Config服务发现支持
spring.cloud.config.discovery.serviceId :指定server端的name,也就是server端spring.application.name的值
eureka.client.serviceUrl.defaultZone :指向配置中心的地址
这三个配置文件都需要放到bootstrap.properties的配置中
⑶启动类
启动类添加@EnableDiscoveryClient激活对配置中心的支持
@EnableDiscoveryClient
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
启动client端,在浏览器中访问:http://localhost:8000/ 就会看到server端和client端都已经注册了到注册中心了。
五、基于Webhook和消息总线的解决方案
1.基本原理图
这时Spring Cloud Bus做配置更新步骤如下:
⑴提交代码触发post请求给bus/refresh
⑵server端接收到请求并发送给Spring Cloud Bus
⑶Spring Cloud bus接到消息并通知给其它客户端
⑷其它客户端接收到通知,请求Server端获取最新配置
⑸全部客户端均获取到最新的配置
2.客户端
⑴添加依赖
需要多引入spring-cloud-starter-bus-amqp包,增加对消息总线的支持
org.springframework.cloud
spring-cloud-starter-bus-amqp
⑵修改配置文件
## 刷新时,关闭安全验证
management.security.enabled=false
## 开启消息跟踪
spring.cloud.bus.trace.enabled=true
spring.rabbitmq.host=192.168.9.89
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=123456
3.服务端
⑴添加依赖
需要多引入spring-cloud-starter-bus-amqp包,增加对消息总线的支持
org.springframework.cloud
spring-cloud-config-server
org.springframework.cloud
spring-cloud-starter-bus-amqp
org.springframework.cloud
spring-cloud-starter-eureka
⑵修改配置文件
server:
port: 8001
spring:
application:
name: spring-cloud-config-server
cloud:
config:
server:
git:
uri: https://github.com/ityouknow/spring-cloud-starter/ # 配置git仓库的地址
search-paths: config-repo # git仓库地址下的相对地址,可以配置多个,用,分割。
username: username # git仓库的账号
password: password # git仓库的密码
rabbitmq:
host: 192.168.0.6
port: 5672
username: admin
password: 123456
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8000/eureka/ ## 注册中心eurka地址
management:
security:
enabled: false //配置文件要注意格式,要不无效!!!
4.测试
我们将github上的文件
neo.hello=hello im dev update bus edit edit
改成:
neo.hello=hello im dev update bus edit edit zuizhong
然后执行一个CURL:
curl -X POST http://localhost:8001/bus/refresh
然后读8001(配置服务器端):
http://localhost:8001/neo-config-dev.properties
显示:
neo.hello: hello im dev update bus edit edit zuizhong
然后我们读:
8002客户端:
http://localhost:8002/hello
输出:
hello im dev update bus edit edit zuizhong
8003客户端:
http://localhost:8003/hello
输出:
hello im dev update bus edit edit zuizhong