随着工程量的越来越大,每个工程里面都需要去进行配置,导致大量的时间都花费在了修改配置文件上,所以集中配置非常的重要。
需要有一个配置中心,然后其他服务全部从配置中心上获取配置,获取到配置后可以动态的在当前服务中更新配置信息。
Spring Cloud Config
服务端的搭建
坐标:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
配置:
spring:
application:
name: cloud-config-server
cloud:
config:
server:
git:
uri: git@gitee.com:lunaticy/config.git
label: master
上面配置文件配置了git
的远程地址,还规定了到master
分支上面去找文件
这里有个坑,如果是Windows
电脑,不要使用Git Bash
去生成SSH
密钥,使用默认的CMD
就好了,不然总是鉴权失败,原因是私钥不是RSA
,而是OpenSSH
,这就导致私钥不正确。
启动类:
@SpringBootApplication
@EnableConfigServer
public class ConfigServerApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}
}
启动后有5种访问方式:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties
他们分别对应的URL是:
http://localhost:8844/cloud/dev/master (JSON)
http://localhost:8844/cloud-dev.yml (Yaml)
http://localhost:8844/master/cloud-dev.yml (Yaml)
http://localhost:8844/cloud-dev.properties (Properties)
http://localhost:8844/master/cloud-dev.properties (Properties)
客户端的搭建
依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
配置(bootstrap.yaml
):
bootstrap.yaml
比application.yaml
优先级高一些,所以适用于动态配置文件的加载。
spring:
application:
name: config-client
cloud:
config:
label: master
name: cloud
profile: dev
uri: http://localhost:8844
一个普普通通的启动类,还有一个普普通通的Controller
:
@SpringBootApplication
public class ConfigClientApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApplication.class, args);
}
}
@RestController
public class ConfigController {
@Value("${display.info}")
private String info;
@RequestMapping("info")
public String info() {
return info;
}
}
启动后,访问接口,可以看到Git上配置文件种存储的字符串就代表成功了。
上面演示了只有一个客户端的情况,Git上面的配置文件更改了之后,发现Config Server
接口中的配置变了,但是Config Client
里面的配置并没有改变,重启后就改变了。
如果有超级多个客户端,不可能一直去做微服务的重启操作,所以就需要有一个热配置,也就是动态刷新配置。
动态刷新配置
该操作在客户端
首先需要加入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
然后暴露出端点,在之前Hystrix Dashboard
配置的基础上添加一个refresh
:
management:
endpoints:
web:
exposure:
include: health, info, hystrix.stream, refresh
接下来是最重要的一步,在之前的Controller
上面加上@RefreshScope
,主意一定是作用域的Controller
上,不能加载主启动类上。
@RestController
@RefreshScope
public class ConfigController {
...
}
每次修改之后用post
方法发送refresh
请求就可以做到动态的加载配置文件了。
http://localhost:8855/actuator/refresh
虽然达成目标,但是这还是在一个微服务的基础上,如果微服务数量相当多,难道要每个微服务发送一个请求?这也好实现,但是还要精确的控制哪些微服务需要刷新,哪些微服务不需要刷新。SpringCloud
也有一套解决方案,叫做Spring Cloud Bus
,消息总线。
Spring Cloud Bus
实现原理就是用消息中间件做所有微服务的通知工作,只需要发送一次请求,就会通知给其他微服务,其他微服务收到通知后就会自动的刷新配置。
发送一次请求,发给谁合适呢,有两种方案:
-
发给
Config Server
这种方案是最好的方案,让配置中心去通知所有使用了配置中心的微服务
-
发送
Config Client
这种方案并不优雅,因为会让其中的一个微服务多做一点事情,而且成千上万个微服务之中就它特殊,也不是一件漂亮的事情。
安装RabbitMQ
略掉了... 在之前RabbitMQ
的文章中记录过...
而且网上的教程也不少...
Bus全局动态刷新
该操作在服务端
因为要使用Config Server
做广播的一端,所以就需要Config Server
来暴露一个接口,访问该接口就可以广播给所有的Config Client
引入依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
添加配置:
spring:
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
management:
endpoints:
web:
exposure:
include: bus-refresh
可以看到配置文件配置了RabbitMQ
的连接,还暴漏了端点bus-refresh
服务端就改写完成了,接下来需要新建几个客户端,以一个为例:
加入一样的依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
配置文件配置一下RabbitMQ
就可以了。
启动服务端和几个客户端进行测试,客户端如果不想要新建好几个,可以用新建启动配置的方式:
然后用Postman
来发送一个Post
请求
http://localhost:8844/actuator/bus-refresh
可以看到批量的进行配置刷新了。
Bus定点动态刷新
和上面唯一的不同是Postman
发送的接口不一样了。
http://localhost:8844/actuator/bus-refresh/config-client:8855
在原来的URL上面添加了服务名:端口号
除了使用Postman
以外,可以使用远程仓库的Webhook
功能来进行实时的配置改变,也就相当于改了文件之后Gitee
会自动触发某个接口,当然这个接口需要在公网才可以。