分布式配置中心是如何通过组合方式获取环境配置?

举报
溜溜丽 发表于 2021/07/01 20:32:36 2021/07/01
【摘要】 《配置中心 Spring Cloud Config 详解》系列文章更新,一起在技术的路上精进!本系列文章将会介绍Spring Cloud 中提供了分布式配置中心Spring Cloud Config。应用服务中除了实现系统功能的代码,还需要连接资源和其它应用,经常有很多需要在外部配置的数据去调整应用的行为,如切换不同的数据库,设置功能开关等。随着微服务的不断增加,需要系统具备可伸缩和可扩展性...

《配置中心 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的实现,将SearchPathCompositeEnvironmentRepositoryCompositeEnvironmentRepository加入到Spring的上下文中,分别对应于之前讲的SearchPathLocatorEnvironmentRepository。下面看一下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 的情况下,通过组合方式获取环境配置的实现。下面的文章将会重点介绍客户端如何获取指定服务的资源文件。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。