新闻资讯
Spring Cloud Config源码分析
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
回复列表