日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

環境:Springboot2.3.12.RELEASE + Spring Cloud Alibaba2.2.5.RELEASE + Spring Cloud Hoxton.SR12

應用的核心技術是:自定義PropertySourceLocator,然后配置spring.factories

在如下包中配置:


spring-cloud-context-xxx.jar中

org.springframework.cloud.bootstrap.BootstrapConfiguration=
org.springframework.cloud.bootstrap.config.PropertySourceBootstrapConfiguration

Nacos加載配置的時候默認會通過一下三個DataId加載數據:

核心類:
NacosPropertySourceLocator

  1. dataId=nacos-config, tenant(namespace)=7205e694-ac51-4ac1-bbe9-87c28689b88a, group=HisGroup
  2. loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,
    fileExtension, true);
  3. dataId=nacos-config.properties, tenant=7205e694-ac51-4ac1-bbe9-87c28689b88a, group=HisGroup
  4. loadNacosDataIfPresent(compositePropertySource,
    dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
  5. 通過定義的profile
  6. private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";
    private static final String SEP1 = "-";
    private static final String DOT = ".";
    for (String profile : environment.getActiveProfiles()) {
    String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
    loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
    fileExtension, true);
    }

自動配置核心

@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigBootstrapConfiguration {
    // Nacos Config相關的配置屬性
    @Bean
    @ConditionalOnMissingBean
    public NacosConfigProperties nacosConfigProperties() {
        return new NacosConfigProperties();
    }
    
    // 管理Nacos Config相關的服務
    @Bean
    @ConditionalOnMissingBean
    public NacosConfigManager nacosConfigManager(
            NacosConfigProperties nacosConfigProperties) {
        return new NacosConfigManager(nacosConfigProperties);
    }
    
    // 核心類自定義啟動加載配置文件(Bootstraps)
    @Bean
    public NacosPropertySourceLocator nacosPropertySourceLocator(
            NacosConfigManager nacosConfigManager) {
        return new NacosPropertySourceLocator(nacosConfigManager);
    }
}
org.springframework.cloud.bootstrap.BootstrapConfiguration=
com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration

自定義屬性源

public class NacosPropertySourceLocator implements PropertySourceLocator {
    private NacosPropertySourceBuilder nacosPropertySourceBuilder;
    private NacosConfigProperties nacosConfigProperties;
    private NacosConfigManager nacosConfigManager;
    public NacosPropertySourceLocator(NacosConfigManager nacosConfigManager) {
        this.nacosConfigManager = nacosConfigManager;
        this.nacosConfigProperties = nacosConfigManager.getNacosConfigProperties();
    }
    public PropertySource<?> locate(Environment env) {
        nacosConfigProperties.setEnvironment(env);
        // 關鍵通過NacosConfigManager獲取ConfigService服務
        ConfigService configService = nacosConfigManager.getConfigService();
        // ...
        long timeout = nacosConfigProperties.getTimeout();
        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);// NACOS_PROPERTY_SOURCE_NAME = NACOS
        // 加載共享配置
        loadSharedConfiguration(composite);
        // 加載擴展配置
        loadExtConfiguration(composite);
        // 加載應用程序配置(這里就以應用程序配置,深入查看)
        loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);

        return composite;
    }
}

獲取配置服務

ConfigService配置服務是獲取配置信息的核心方法:

public interface ConfigService {
    
    // 獲取配置
    String getConfig(String dataId, String group, long timeoutMs) throws NacosException;
    
    // 獲取配置并設置監聽
    String getConfigAndSignListener(String dataId, String group, long timeoutMs, Listener listener)
            throws NacosException;
    
    // 給配置添加監聽
    void addListener(String dataId, String group, Listener listener) throws NacosException;
    
    // 發布配置
    boolean publishConfig(String dataId, String group, String content) throws NacosException;
    
    // 刪除配置
    boolean removeConfig(String dataId, String group) throws NacosException;
    
    // 刪除監聽
    void removeListener(String dataId, String group, Listener listener);
    
    // 獲取服務狀態
    String getServerStatus();
    
    // 關閉資源服務
    void shutDown() throws NacosException;
}

NacosConfigManager

public class NacosConfigManager {
    private static ConfigService service = null;
    private NacosConfigProperties nacosConfigProperties;
    public NacosConfigManager(NacosConfigProperties nacosConfigProperties) {
        this.nacosConfigProperties = nacosConfigProperties;
        // 創建配置服務
        createConfigService(nacosConfigProperties);
    }
    static ConfigService createConfigService(
            NacosConfigProperties nacosConfigProperties) {
        if (Objects.isNull(service)) {
            synchronized (NacosConfigManager.class) {
                try {
                    if (Objects.isNull(service)) {
                        // 通過工廠創建服務
                        // assembleConfigServiceProperties方法
                        // 就是收集關于Nacos所有配置信息,如:地址,端口,用戶名,密碼等
                        // 詳細查看NacosConfigProperties#assembleConfigServiceProperties
                        service = NacosFactory.createConfigService(
                                nacosConfigProperties.assembleConfigServiceProperties());
                    }
                }
                // ...
            }
        }
        return service;
    }
}
// NacosFactory
public class NacosFactory {
    public static ConfigService createConfigService(Properties properties) throws NacosException {
        return ConfigFactory.createConfigService(properties);
    }
}
public class ConfigFactory {
    public static ConfigService createConfigService(Properties properties) throws NacosException {
        try {
            Class<?> driverImplClass = Class.forName("com.alibaba.nacos.client.config.NacosConfigService");
            Constructor constructor = driverImplClass.getConstructor(Properties.class);
            ConfigService vendorImpl = (ConfigService) constructor.newInstance(properties);
            // 通過反射構造了NacosConfigservice,同時設置屬性信息
            // 這些屬性信息就是一些Naocs服務的地址,端口,用戶名,密碼等信息
            return vendorImpl;
        } catch (Throwable e) {
            throw new NacosException(NacosException.CLIENT_INVALID_PARAM, e);
        }
    }
}

到此就得到了一個ConfigService服務類NacosConfigService。

獲取應用程序配置

接著95.2獲取到了ConfigService以后繼續執行

public class NacosPropertySourceLocator implements PropertySourceLocator {
    private NacosPropertySourceBuilder nacosPropertySourceBuilder;
    public PropertySource<?> locate(Environment env) {
        nacosConfigProperties.setEnvironment(env);
        // 關鍵通過NacosConfigManager獲取ConfigService服務
        ConfigService configService = nacosConfigManager.getConfigService();
        // ...
        nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,
                timeout);
        CompositePropertySource composite = new CompositePropertySource(
                NACOS_PROPERTY_SOURCE_NAME);
        loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
        return composite;
    }
    private void loadApplicationConfiguration(
            CompositePropertySource compositePropertySource, String dataIdPrefix,
            NacosConfigProperties properties, Environment environment) {
        // 獲取文件擴展
        String fileExtension = properties.getFileExtension();
        // 獲取分組
        String nacosGroup = properties.getGroup();
        // ...
        // load with suffix, which have a higher priority than the default
        // 這里就以這里為例
        loadNacosDataIfPresent(compositePropertySource,
                dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
        // Loaded with profile, which have a higher priority than the suffix
        // 這里會根據不同配置的profiles再次加載不同環境的配置
        for (String profile : environment.getActiveProfiles()) {
            String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
            loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
                    fileExtension, true);
        }

    }
    private void loadNacosDataIfPresent(final CompositePropertySource composite,
            final String dataId, final String group, String fileExtension,
            boolean isRefreshable) {
        if (null == dataId || dataId.trim().length() < 1) {
            return;
        }
        if (null == group || group.trim().length() < 1) {
            return;
        }
        // 加載Nacos屬性源
        NacosPropertySource propertySource = this.loadNacosPropertySource(dataId, group,
                fileExtension, isRefreshable);
        this.addFirstPropertySource(composite, propertySource, false);
    }
    private NacosPropertySource loadNacosPropertySource(final String dataId,
            final String group, String fileExtension, boolean isRefreshable) {
        // ...
        return nacosPropertySourceBuilder.build(dataId, group, fileExtension,
                isRefreshable);
    }
    private void addFirstPropertySource(final CompositePropertySource composite,
            NacosPropertySource nacosPropertySource, boolean ignoreEmpty) {
        if (null == nacosPropertySource || null == composite) {
            return;
        }
        if (ignoreEmpty && nacosPropertySource.getSource().isEmpty()) {
            return;
        }
        composite.addFirstPropertySource(nacosPropertySource);
    }
}
// 這里面開始加載數據
public class NacosPropertySourceBuilder {
    NacosPropertySource build(String dataId, String group, String fileExtension,
            boolean isRefreshable) {
        Map<String, Object> p = loadNacosData(dataId, group, fileExtension);
        NacosPropertySource nacosPropertySource = new NacosPropertySource(group, dataId,
                p, new Date(), isRefreshable);
        NacosPropertySourceRepository.collectNacosPropertySource(nacosPropertySource);
        return nacosPropertySource;
    }
    // 加載數據
    private Map<String, Object> loadNacosData(String dataId, String group,
            String fileExtension) {
        String data = null;
        try {
            // 通過ConfigService加載配置內容(從遠程服務獲取)
            data = configService.getConfig(dataId, group, timeout);
            if (StringUtils.isEmpty(data)) {
                return EMPTY_MAP;
            }
            Map<String, Object> dataMap = NacosDataParserHandler.getInstance()
                    .parseNacosData(data, fileExtension);
            return dataMap == null ? EMPTY_MAP : dataMap;
        }
        // ...
        return EMPTY_MAP;
    }
}
public class NacosConfigService implements ConfigService {
    public String getConfig(String dataId, String group, long timeoutMs) throws NacosException {
        return getConfigInner(namespace, dataId, group, timeoutMs);
    }
    private String getConfigInner(String tenant, String dataId, String group, long timeoutMs) throws NacosException {
        group = null2defaultGroup(group);
        ParamUtils.checkKeyParam(dataId, group);
        ConfigResponse cr = new ConfigResponse();
        
        cr.setDataId(dataId);
        cr.setTenant(tenant);
        cr.setGroup(group);
        
        // 這里會從緩存文件中獲取,如果能獲取就不會再從遠程加載了
        // 會從如下緩存目錄下加載配置:
        // System.getProperty("JM.SNAPSHOT.PATH", 
        // System.getProperty("user.home")) + File.separator + "nacos" 
        // + File.separator + "config"
        String content = LocalConfigInfoProcessor.getFailover(agent.getName(), dataId, group, tenant);
        if (content != null) {
            cr.setContent(content);
            configFilterChainManager.doFilter(null, cr);
            content = cr.getContent();
            return content;
        }
        
        try {
            // 緩存總無法獲取則從遠程服務上拉取數據
            String[] ct = worker.getServerConfig(dataId, group, tenant, timeoutMs);
            cr.setContent(ct[0]);
            
            configFilterChainManager.doFilter(null, cr);
            content = cr.getContent();
            
            return content;
        } catch (NacosException ioe) {
            if (NacosException.NO_RIGHT == ioe.getErrCode()) {
                throw ioe;
            }
        }
        content = LocalConfigInfoProcessor.getSnapshot(agent.getName(), dataId, group, tenant);
        cr.setContent(content);
        configFilterChainManager.doFilter(null, cr);
        content = cr.getContent();
        return content;
    }
}
public class ClientWorker implements Closeable {
     // 這里就是從遠程服務拉取配置
     public String[] getServerConfig(String dataId, String group, String tenant, long readTimeout)
            throws NacosException {
        String[] ct = new String[2];
        if (StringUtils.isBlank(group)) {
            group = Constants.DEFAULT_GROUP;
        }
        
        HttpRestResult<String> result = null;
        try {
            Map<String, String> params = new HashMap<String, String>(3);
            if (StringUtils.isBlank(tenant)) {
                params.put("dataId", dataId);
                params.put("group", group);
            } else {
                params.put("dataId", dataId);
                params.put("group", group);
                params.put("tenant", tenant);
            }
            result = agent.httpGet(Constants.CONFIG_CONTROLLER_PATH, null, params, agent.getEncode(), readTimeout);
        } catch (Exception ex) {
            throw new NacosException(NacosException.SERVER_ERROR, ex);
        }
        
        switch (result.getCode()) {
            case HttpURLConnection.HTTP_OK:
                // 獲取成功后會將數據保存到緩存目錄下
                LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, result.getData());
                ct[0] = result.getData();
                if (result.getHeader().getValue(CONFIG_TYPE) != null) {
                    ct[1] = result.getHeader().getValue(CONFIG_TYPE);
                } else {
                    ct[1] = ConfigType.TEXT.getType();
                }
                return ct;
            case HttpURLConnection.HTTP_NOT_FOUND:
                LocalConfigInfoProcessor.saveSnapshot(agent.getName(), dataId, group, tenant, null);
                return ct;
            case HttpURLConnection.HTTP_CONFLICT: {
                throw new NacosException(NacosException.CONFLICT,
                        "data being modified, dataId=" + dataId + ",group=" + group + ",tenant=" + tenant);
            }
                throw new NacosException(result.getCode(), result.getMessage());
            }
            default: {
                throw new NacosException(result.getCode(),
                        "http error, code=" + result.getCode() + ",dataId=" + dataId + ",group=" + group + ",tenant="
                                + tenant);
            }
        }
    }
}

到此就完成了遠程配置數據的加載

總結:Nacos Config先從本地緩存中獲取數據,如果不能獲取才從遠程拉取(如果遠程服務無法連接,那么會不斷重試,前提是本地能夠加載到數據,否則服務將無法正常啟動)。

完畢!!!

分享到:
標簽:Spring Cloud
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定