1. 程式人生 > >SpringCloud配置重新整理機制的簡單分析[nacos為例子]

SpringCloud配置重新整理機制的簡單分析[nacos為例子]

### SpringCloud Nacos 1. 本文主要分為SpringCloud Nacos的設計思路 2. 簡單分析一下觸發重新整理事件後發生的過程以及一些踩坑經驗 #### org.springframework.cloud.bootstrap.config.PropertySourceLocator 1. 這是一個SpringCloud提供的啟動器載入配置類,實現locate,注入到上下文中即可發現配置 ``` /** * @param environment The current Environment. * @return A PropertySource, or null if there is none. * @throws IllegalStateException if there is a fail-fast condition. */ PropertySource locate(Environment environment); ``` 2. com.alibaba.cloud.nacos.client.NacosPropertySourceLocator - 該類為nacos實現的配置發現類 3. org.springframework.core.env.PropertySource - 改類為springcloud抽象出來表達屬性源的類 - com.alibaba.cloud.nacos.client.NacosPropertySource / nacos實現了這個類,並賦予了其他屬性 ``` /** * Nacos Group. */ private final String group; /** * Nacos dataID. */ private final String dataId; /** * timestamp the property get. */ private final Date timestamp; /** * Whether to support dynamic refresh for this Property Source. */ private final boolean isRefreshable; ``` #### 大概講解com.alibaba.cloud.nacos.client.NacosPropertySourceLocator#locate 1. 原始碼解析 ``` @Override public PropertySource locate(Environment env) { nacosConfigProperties.setEnvironment(env); // 獲取nacos配置的服務類,http協議,訪問nacos的api介面獲得配置 ConfigService configService = nacosConfigManager.getConfigService(); if (null == configService) { log.warn("no instance of config service found, can't load config from nacos"); return null; } long timeout = nacosConfigProperties.getTimeout(); // 構建一個builder nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService, timeout); String name = nacosConfigProperties.getName(); String dataIdPrefix = nacosConfigProperties.getPrefix(); if (StringUtils.isEmpty(dataIdPrefix)) { dataIdPrefix = name; } if (StringUtils.isEmpty(dataIdPrefix)) { dataIdPrefix = env.getProperty("spring.application.name"); } // 構建一個複合資料來源 CompositePropertySource composite = new CompositePropertySource( NACOS_PROPERTY_SOURCE_NAME); // 載入共享的配置 loadSharedConfiguration(composite); // 載入擴充套件配置 loadExtConfiguration(composite); // 載入應用配置,應用配置的優先順序是最高,所以這裡放在最後面來做,是因為新增配置的地方都是addFirst,所以最先的反而優先順序最後 loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env); return composite; } ``` 2. 每次nacos檢查到配置更新的時候就會觸發上下文配置重新整理,就會調取locate這個方法 #### org.springframework.cloud.endpoint.event.RefreshEvent 1. 該事件為spring cloud內建的事件,用於重新整理配置 #### com.alibaba.cloud.nacos.refresh.NacosRefreshHistory 1. 該類用於nacos刷新歷史的存放,用來儲存每次拉取的配置的md5值,用於比較配置是否需要重新整理 #### com.alibaba.cloud.nacos.refresh.NacosContextRefresher 1. 該類是Nacos用來管理一些內部監聽器的,主要是配置重新整理的時候可以出發回撥,並且發出spring cloud上下文的配置重新整理事件 #### com.alibaba.cloud.nacos.NacosPropertySourceRepository 1. 該類是nacos用來儲存拉取到的資料的 2. 流程: - 重新整理器檢查到配置更新,儲存到NacosPropertySourceRepository - 發起重新整理事件 - locate執行,直接讀取NacosPropertySourceRepository #### com.alibaba.nacos.client.config.NacosConfigService 1. 該類是nacos的主要重新整理配置服務類 2. com.alibaba.nacos.client.config.impl.ClientWorker - 該類是服務類裡主要的客戶端,協議是HTTP - clientWorker啟動的時候會初始化2個執行緒池,1個用於定時檢查配置,1個用於輔助檢查 ``` executor = Executors.newScheduledThreadPool(1, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("com.alibaba.nacos.client.Worker." + agent.getName()); t.setDaemon(true); return t; } }); executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName()); t.setDaemon(true); return t; } }); executor.scheduleWithFixedDelay(new Runnable() { @Override public void run() { try { checkConfigInfo(); } catch (Throwable e) { LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e); } } }, 1L, 10L, TimeUnit.MILLISECONDS); ``` 3. com.alibaba.nacos.client.config.impl.ClientWorker.LongPollingRunnable - 該類用於長輪詢任務 - com.alibaba.nacos.client.config.impl.CacheData#checkListenerMd5比對MD5之後開始重新整理配置 #### com.alibaba.cloud.nacos.parser 1. 該包提供了很多檔案型別的轉換器 2. 載入資料的時候會根據副檔名去查詢一個轉換器例項 ``` // com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder#loadNacosData private Map