新闻资讯

新闻资讯 行业动态

Spring Cloud Config源码分析

编辑:008     时间:2020-02-28

config client


首先关注一下引导配置类ConfigServiceBootstrapConfiguration,它的作用是在SpringBoot上下文启动时读取resources目录下的bootstrap.properties文件,取出前缀名为spring.cloud.config的配置项,这些配置项通常包含config server的节点信息、连接该节点所需要的权限配置以及客户端所要抓取的配置信息,并以此初始化ConfigClientProperties,

@Bean
public ConfigClientProperties configClientProperties() {
    ConfigClientProperties client = new ConfigClientProperties(this.environment);
    return client;
}

@Bean
@ConditionalOnProperty(value = "spring.cloud.config.enabled", matchIfMissing = true)
public ConfigServicePropertySourceLocator configServicePropertySource() {
    ConfigServicePropertySourceLocator locator = new ConfigServicePropertySourceLocator(
            configClientProperties());
    return locator;
}

进而实例化ConfigServicePropertySourceLocator,而后者实质上是一个属性资源定位器,其locate方法拥有通过http的方式向config服务端请求配置文件的功能。

另一个重要的类是PropertySourceBootstrapConfiguration,它实现了ApplicationContextInitializer接口,该接口会在应用上下文刷新之前(refresh())被回调,从而做一些初始化动作,简易的函数调用栈如下:

SpringApplicationBuilder.run() -> SpringApplication.run() -> SpringApplication.createAndRefreshContext() -> SpringApplication.applyInitializers() -> PropertySourceBootstrapConfiguration.initialize()

而上述ConfigServicePropertySourceLocator的locate方法会在initialize中被调用,从而保证上下文在refresh之前能够拿到必要的配置信息。



config server


同client一样,我们首先分析引导配置类ConfigServerBootstrapConfiguration,他的作用同样是初始化资源定位器EnvironmentRepositoryPropertySourceLocator,后者可以从一个叫做EnvironmentRepository的地方获取配置。

默认情况下这个引导配置类是关闭状态,原因是它可能会延迟整个项目的启动,我们可以显式的配置spring.cloud.config.server.bootstrap=true使其生效。EnvironmentRepository类似于其他应用的dao层,它对配置文件的访问做了一层抽象,一共有三类,分别支持从本地、svn以及git获取配置文件。而直接接受client请求的则是EnvironmentController,它实际上和我们业务应用中的RestController一样,get到url中的参数并依此调用EnvironmentRepository.find()方法,最后将配置返回给client端,典型的代码如下:

@RequestMapping("/{name}/{profiles}/{label:.*}")
public Environment labelled(@PathVariable String name, @PathVariable String profiles,
        @PathVariable String label) {
    if (label != null && label.contains("(_)")) {
        // "(_)" is uncommon in a git branch name, but "/" cannot be matched
        // by Spring MVC
        label = label.replace("(_)", "/");
    }
    Environment environment = this.repository.findOne(name, profiles, label);
    return environment;
}

通过debugger可以发现,这里的Environment实际上是EnvironmentEncryptorEnvironmentRepository,它自己不会去获取配置而是委托给成员变量MultipleJGitEnvironmentRepository去做,它只负责后续必要的解码工作(是的,我们可以对配置文件进行加密使其更安全!):

@Override
public Environment findOne(String name, String profiles, String label) {
    Environment environment = this.delegate.findOne(name, profiles, label);
    if (this.environmentEncryptor != null) {
        environment = this.environmentEncryptor.decrypt(environment);
    }
    if (!this.overrides.isEmpty()) {
        environment.addFirst(new PropertySource("overrides", this.overrides));
    }
    return environment;
}

MultipleJGitEnvironmentRepository继承自JGitEnvironmentRepository,不用怀疑它的作用就是通过发起HTTP或者SSH连接去config-repo获取配置文件。

如此一来我们大致可以将config-client,config-server和config-repo串连起来,反过来再去理解一下这套工具的使用,是不是觉得水到渠成。但是实际上spring-cloud-config还具有很多其它让人惊喜的功能,比如本地缓存配置文件,在一定程度上允许你的server挂一会儿,比如加解密功能,让配置文件的管理和传输更加安全放心,甚至你还可以通过某些方法在client运行时动态的去刷新配置,连变更配置文件都不需要重启了,是不是很酷!期待大家对spring-cloud-config的深入挖掘!


原文链接:https://mp.weixin.qq.com/s/p_fRaVAfAKPsYe2FtaNbJg

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

回复列表

相关推荐