分布式配置中心的多 JGit 仓库是如何匹配与实现?

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

《配置中心 Spring Cloud Config 详解》系列文章更新,一起在技术的路上精进!本系列文章将会介绍Spring Cloud 中提供了分布式配置中心Spring Cloud Config。应用服务中除了实现系统功能的代码,还需要连接资源和其它应用,经常有很多需要在外部配置的数据去调整应用的行为,如切换不同的数据库,设置功能开关等。随着微服务的不断增加,需要系统具备可伸缩和可扩展性,除此之外就是管理相当多的服务实例的配置数据。在应用的开发阶段由各个服务自治,但是到了生产环境之后会给运维带来很大的麻烦,特别是微服务的规模比较大,配置的更新更为麻烦。为此,系统需要建立一个统一的配置管理中心。

在前面的文章,我们介绍了 JGit 获取最新的远端仓库配置以及多 JGit 仓库实现。本文将会进一步介绍多个 repos 的匹配规则,这也是多 JGit 仓库实现的一个关键步骤。

多个 repos 的匹配规则

前面已经说过,MultipleJGitEnvironmentRepository是环境仓库的默认实现方式,继承自JGitEnvironmentRepository,支持Git地址的占位符,模式匹配以及多个仓库的配置。上面截取的代码中,定义了repos变量,该表量是一个Map类型,key对应每一个repo名字,value则是静态内部类PatternMatchingJGitEnvironmentRepository。下面我们具体看一下,多个repo规则是在源码中的实现。

public static class PatternMatchingJGitEnvironmentRepository
			extends JGitEnvironmentRepository {

		private String[] pattern = new String[0]; // 1
		private String name; // 2
		...
		public boolean matches(String application, String profile, String label) { // 3
			...
			String[] profiles = StringUtils.commaDelimitedListToStringArray(profile);
			for (int i = profiles.length; i-- > 0;) {
				if (PatternMatchUtils.simpleMatch(this.pattern,
						application + "/" + profiles[i])) { // 4
					return true;
				}
			}
			return false;
		}

		public void setPattern(String[] pattern) { // 5
			Collection<String> patterns = new ArrayList<>();
			List<String> otherProfiles = new ArrayList<>();
			for (String p : pattern) {
				if (p != null) {
					if (!p.contains("/")) { // 6
						patterns.add(p + "/*");
					}
					if (!p.endsWith("*")) { // 7
						otherProfiles.add(p + ",*");
					}
				}
				patterns.add(p);
			}
			patterns.addAll(otherProfiles);
			...
			this.pattern = patterns.toArray(new String[0]);
		}
	}
}
  1. 匹配application和profiles的模式串数组;
  2. 仓库名,默认为map的key值;
  3. 匹配application、profile与模式串是否匹配;
  4. 匹配给定模式的字符串;
  5. pattern的setter方法,用来补全一些缺省书写格式;
  6. 缺少profile的情况, 将会补齐"/ * ",匹配任意的profile;
  7. 不以 * 结尾的情况,即指定了profile,默认规则会补齐", * "。

通过模式匹配{application}/{profile},可以实现更复杂的需求,pattern可以使用通配符支持列表的形式。在PatternMatchingJGitEnvironmentRepository中,由于继承自JGitEnvironmentRepository,所以模式匹配这种模式实现了获取应用服务配置信息等方法。

PatternMatchingJGitEnvironmentRepository 对patterns进行了预处理,在pattern的setter方法中补全一些配置缺省书写格式,如上面提到的缺省profile的情况。matches方法匹配application、profile与模式串是否匹配,这边主要调用的是Spring的工具类方法进行判断。#simpleMatch是Spring util中的工具类PatternMatchUtils提供的方法,用于处理目标字符串与模式串是否匹配。

	public static boolean simpleMatch(String pattern, String str) {
		if (pattern == null || str == null) {
			return false;
		}
		int firstIndex = pattern.indexOf('*');
		if (firstIndex == -1) { // 1
			return pattern.equals(str);
		}
		if (firstIndex == 0) { // 2
			if (pattern.length() == 1) {
				return true;
			}
			int nextIndex = pattern.indexOf('*', firstIndex + 1);
			if (nextIndex == -1) { // 3
				return str.endsWith(pattern.substring(1));
			}
			String part = pattern.substring(1, nextIndex); // 4
			if ("".equals(part)) { //5
				return simpleMatch(pattern.substring(nextIndex), str);
			int partIndex = str.indexOf(part); // 6
			while (partIndex != -1) { // 7
				if (simpleMatch(pattern.substring(nextIndex), str.substring(partIndex + part.length()))) {
					return true;
				}
				partIndex = str.indexOf(part, partIndex + 1);
			}
			return false;
		}
		return (str.length() >= firstIndex &&
				pattern.substring(0, firstIndex).equals(str.substring(0, firstIndex)) &&
				simpleMatch(pattern.substring(firstIndex), str.substring(firstIndex))); // 8
	}
  1. 如果没有通配符,严格匹配
  2. 处理以 * 开头的情况
  3. 如果只有一个 * ,后半部分严格匹配
  4. 截断第一个 * 与第二个*之间的字符串
  5. 处理后半部分为空的情况
  6. 目标串索引到该part
  7. 索引到的情况,递归验证后续字符串,否则失败
  8. 最后将前半部分进行严格匹配,后半部分进行递归调用

利用Spring的工具类方法进行判断,匹配给定模式的字符串,支持以下简单模式样式:“xxx ”,“ xxx”,“* xxx *”和“xxx * yyy”(具有任意数量的模式部分),以及完全相等的匹配模式。

小结

本文主要介绍了 Spring Cloud Config 服务端 Config Server 中多个 repos 的匹配规则的实现。在有些场景下,我们可能需要从多个环境仓库中拉取配置数据。通过在 config server 中的 application.properties 或 application.yml 激活多个 profile,比如同时从 Git 和 SVN 仓库拉取配置数据,下面的文章将会重点介绍如何通过组合方式获取环境配置。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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