一、简介
配置文件如果改变了,已经启动的服务如何获得最新的配置,当然可以重新启动服务,但是这样速度太慢了,还需要到服务器上去操作,增加了运维成本,spring cloud提供了一个手动刷新的解决方案。
二、客户端刷新
客户端刷新是调用单个客户端的端点刷新接口,这样只刷新被调用刷新接口的端点。
端点配置
spring cloud在actuator中提供了一个refresh端点,通过该端点可以进行刷新。
客户端引入actuator
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
复制代码 客户端引入spring security
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-security</artifactId>
- </dependency>
复制代码 配置management并暴露端点
- management:
- server:
- port: 8101
- servlet:
- context-path: /demo/configClient/admin
- endpoints:
- web:
- exposure:
- include: "*"
复制代码 在需要刷新的类上加上@RefreshScope注解
- @RefreshScope
- @RestController
- @RequestMapping("testApi")
- public class ConfigTestApi {
-
- @Value("${luminary.test}")
- private String test;
-
- @GetMapping("/config")
- public String server(
- HttpServletRequest request,
- HttpServletResponse response) {
-
- return test;
-
- }
-
- }
复制代码
安全配置对refresh端点不进行csrf防护 - @Configuration
- @EnableWebSecurity
- public class EurekaClientWebSecurityConfig extends WebSecurityConfigurerAdapter {
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
-
- http
- .authorizeRequests()
- // 普通的接口不需要校验
- .antMatchers("/*api/**").permitAll()
- // swagger页面需要添加登录校验
- .antMatchers("/swagger-ui.html").authenticated()
- // 监控节点需要添加登录校验
- .requestMatchers(EndpointRequest.toAnyEndpoint()).authenticated()
- .and()
- // 允许刷新服务
- .csrf().ignoringAntMatchers("/actuator/refresh");
-
- super.configure(http);
-
- }
-
- }
复制代码
刷新通过POST调用客户端的refresh端点,如果配置有改变,返回结果如下 需要注意的是refresh端点是actuator的端点,所以如果配置了management的话,要用management中配置的server.port和server.servlet.context-path
三、服务端刷新 客户端刷新需要每个客户端调用refresh接口,我们希望能在服务端调用刷新接口,然后通知每个客户端进行刷新。 我们需要借助消息总线spring-cloud-bus将刷新信息发送到客户端,目前spring-cloud-bus支持rabbitMq和kafka,这里以kafka做例子。 端点配置 服务端引入actuator,spring security,spring cloud bus,spring cloud config monitor - <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-config-server</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-starter-bus-kafka</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.cloud</groupId>
- <artifactId>spring-cloud-config-monitor</artifactId>
- </dependency>
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-actuator</artifactId>
- </dependency>
复制代码服务端配置management并暴露端点 - management:
- server:
- port: 8168
- servlet:
- context-path: /manage/serverConfig/admin
- endpoints:
- web:
- exposure:
- include: "*"
复制代码客户端在需要刷新的类上加上@RefreshScope注解 - @RefreshScope
- @RestController
- @RequestMapping("testApi")
- public class ConfigTestApi {
-
- @Value("${luminary.test}")
- private String test;
-
- @GetMapping("/config")
- public String server(
- HttpServletRequest request,
- HttpServletResponse response) {
-
- return test;
-
- }
-
- }
复制代码
安全配置对bus-refresh端点不进行csrf防护 - @EnableWebSecurity
- public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
-
- @Override
- protected void configure(HttpSecurity http) throws Exception {
-
- http
- .authorizeRequests()
- .requestMatchers(EndpointRequest.toAnyEndpoint()).authenticated()
- .and()
- .csrf().ignoringAntMatchers("/encrypt", "/decrypt", "/actuator/bus-refresh");
-
- super.configure(http);
-
- }
-
- }
复制代码
KAFKA配置spring cloud bus通过消息队列发送配置变更消息给客户端,目前只支持rabbitMq和kafka,这里选择使用kafka 服务端和客户端配置 - spring:
- cloud:
- stream:
- kafka:
- binder:
- brokers: localhost:9092
- #zk-nodes: localhost:2181 #spring cloud Finchley已弃用,zookeeper会被自动配置
- auto-add-partitions: true
- auto-create-topics: true
- min-partition-count: 1
复制代码
刷新 通过POST调用服务端的bus-refresh端点 需要注意的是bus-refresh端点是actuator的端点,所以如果配置了management的话,要用management中配置的server.port和server.servlet.context-path
|