一、配置中心
先來一張流程圖:
Spring Cloud Bus 如何觸發 Refresh?
注:配置中心里我是配置的mq發送消息
-
RefreshBusEndpoint中加了@Endpoint(
id = "bus-refresh"
)注解,他就會監控這個/actuator/bus-refresh這個路徑 -
然后調用到了busRefresh方法,發布了RefreshRemoteApplicationEvent事件。
-
這個事件發布過程中會使用到ApplicationListenerMethodAdapter來處理,部分代碼如下:
protected Object doInvoke(Object... args) {
Object bean = getTargetBean();
ReflectionUtils.makeAccessible(this.method);
try {
//反射執行的方法是BusAutoConfiguration#acceptLocal()
return this.method.invoke(bean, args);
}
- 反射執行方法會發送mq消息,然后由各個配置中心客戶端接收,接受方法為BusAutoConfiguration#acceptRemote
- 這個方法會發布RefreshRemoteApplicationEvent事件
- 這個事件由RefreshListener負責接收,然后去處理刷新配置
public void onApplicationEvent(RefreshRemoteApplicationEvent event) {
Set<String> keys = this.contextRefresher.refresh();
log.info("Received remote refresh request. Keys refreshed " + keys);
}
- 監聽觸發后,調用到ContextRefresher的refresh()方法
public synchronized Set<String> refresh() {
Set<String> keys = refreshEnvironment();
////對應的bean刷新
this.scope.refreshAll();
return keys;
}
- 先看 refreshEnvironment()方法
public synchronized Set<String> refreshEnvironment() {
//獲取之前的配置
Map<String, Object> before = extract(
this.context.getEnvironment().getPropertySources());
//重新創建一個SpringApplication並獲取新的配置
addConfigFilesToEnvironment();
//比較配置不同的key
Set<String> keys = changes(before,
extract(this.context.getEnvironment().getPropertySources())).keySet();
//發布配置改變事件
this.context.publishEvent(new EnvironmentChangeEvent(context, keys));
return keys;
}
- EnvironmentChangeEvent事件由ConfigurationPropertiesRebinder監聽,監聽到之后會調用rebind方法
@ManagedOperation
public void rebind() {
this.errors.clear();
for (String name : this.beans.getBeanNames()) {
//初始化bean
rebind(name);
}
}
- 再點到this.scope.refreshAll()方法
public void refreshAll() {
//銷毀bean
super.destroy();
this.context.publishEvent(new RefreshScopeRefreshedEvent());
}
- RefreshScopeRefreshedEvent事件由EurekaClientConfigurationRefresher監聽,進行對eureka服務器重連的操作。