目錄
一、簡介
配置文件如果改變了,已經啓動的服務如何獲得最新的配置,當然可以重新啓動服務,但是這樣速度太慢了,還需要到服務器上去操作,增加了運維成本,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