分布式配置中心是如何通过组合方式获取环境配置?
《配置中心 Spring Cloud Config 详解》系列文章更新,一起在技术的路上精进!本系列文章将会介绍Spring Cloud 中提供了分布式配置中心Spring Cloud Config。应用服务中除了实现系统功能的代码,还需要连接资源和其它应用,经常有很多需要在外部配置的数据去调整应用的行为,如切换不同的数据库,设置功能开关等。随着微服务的不断增加,需要系统具备可伸缩和可扩展性,除此之外就是管理相当多的服务实例的配置数据。在应用的开发阶段由各个服务自治,但是到了生产环境之后会给运维带来很大的麻烦,特别是微服务的规模比较大,配置的更新更为麻烦。为此,系统需要建立一个统一的配置管理中心。
在前面的文章,我们进一步介绍了多个 repos 的匹配规则,这也是多 JGit 仓库实现的一个关键步骤。本文将会介绍如何通过组合方式获取配置
如何通过组合方式获取环境配置
CompositeConfiguration
负责配置多个有优先级的EnvironmentRepository
。在有些场景下,我们可能需要从多个环境仓库中拉取配置数据。通过在config server中的application.properties或application.yml激活多个 profile,比如同时从Git和SVN仓库拉取配置数据,可以配置如下的属性:
spring:
profiles:
active: git, svn
cloud:
config:
server:
svn:
uri: file:///path/to/svn/repo
order: 2
git:
uri: file:///path/to/git/repo
order: 1
除了可以指定一个仓库的URI,还可以指定优先级order
属性。order
属性允许你为所有的仓库设置优先级。order
属性的数值越小,优先级越高。仓库之间如果包含相同的属性,优先级属性帮助解决了其潜在的任何冲突。
@Configuration
@ConditionalOnMissingBean(CompositeEnvironmentRepository.class)
public class CompositeConfiguration {
@Bean
@Primary
@ConditionalOnBean(SearchPathLocator.class)
public SearchPathCompositeEnvironmentRepository searchPathCompositeEnvironmentRepository() {
return new SearchPathCompositeEnvironmentRepository(environmentRepos);
}
@Bean
@Primary
@ConditionalOnMissingBean(SearchPathLocator.class)
public CompositeEnvironmentRepository compositeEnvironmentRepository() {
return new CompositeEnvironmentRepository(environmentRepos);
}
//...
}
如上为CompositeConfiguration
的实现,将SearchPathCompositeEnvironmentRepository
和CompositeEnvironmentRepository
加入到Spring的上下文中,分别对应于之前讲的SearchPathLocator
和EnvironmentRepository
。下面看一下CompositeEnvironmentRepository
中的主要实现。
@Override
public Environment findOne(String application, String profile, String label) {
Environment env = new Environment(application, new String[]{profile}, label, null, null);
if(environmentRepositories.size() == 1) {
Environment envRepo = environmentRepositories.get(0).findOne(application, profile, label);
env.addAll(envRepo.getPropertySources());
env.setVersion(envRepo.getVersion());
env.setState(envRepo.getState());
} else {
for (EnvironmentRepository repo : environmentRepositories) {
env.addAll(repo.findOne(application, profile, label).getPropertySources());
}
}
return env;
}
CompositeEnvironmentRepository
实现了EnvironmentRepository
接口,如上为findOne方法的实现。复合环境仓库的模式也比较简单,EnvironmentRepository
的实现是一个数组的形式,首先判断环境仓库的数量,多个则需要遍历,最后调用每种环境仓库的findOne实现。
而SearchPathCompositeEnvironmentRepository
继承自CompositeEnvironmentRepository
,实现了SearchPathLocator
接口,用以获取config文件的路径。
@Override
public Locations getLocations(String application, String profile, String label) {
List<String> locations = new ArrayList<>();
for(EnvironmentRepository repo : this.environmentRepositories) {
if(repo instanceof SearchPathLocator) {
locations.addAll(Arrays.asList(((SearchPathLocator) repo).getLocations(application, profile, label).getLocations()));
}
}
return new Locations(application, profile, label, null, locations.toArray(new String[locations.size()]));
}
实现在之前的基础上,加上了对多个EnvironmentRepository
的遍历处理,整合了多个环境仓库的路径。
当使用复合环境仓库时,不同的仓库都应该包含相同的分支(label)。如果你有一个环境,当你请求Git仓库中label为master的配置数据时,然而SVN仓库并没有包含这样的一个叫做master的分支,就会导致整个请求的失败。另外需要注意的是,当从一个环境仓库获取数值失败时,都会导致复合环境仓库的失败。
除了使用 Spring Cloud 提供的环境仓库,还可以自定义EnvironmentRepository
作为复合仓库的一部分。只需要实现EnvironmentRepository
接口,至于环境仓库的优先级,可以通过Ordered
并覆写 getOrdered
方法,如果没有实现该接口,自定义的环境仓库的优先级默认为最低的。
小结
本文主要介绍了 Spring Cloud Config 服务端 Config Server 中多个 repos 的情况下,通过组合方式获取环境配置的实现。下面的文章将会重点介绍客户端如何获取指定服务的资源文件。
- 点赞
- 收藏
- 关注作者
评论(0)