JGit 获取最新的远端仓库配置以及多JGit仓库实现

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

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

在前面的文章,我们介绍了配置服务器实现中的 JGit 方式实现配置仓库。本文将会进一步介绍 JGit 获取最新的远端仓库配置以及多JGit仓库实现。

JGit 获取最新的远端仓库配置

JGit 方式作为 AbstractScmEnvironmentRepository 子类,#findOne 并没有覆写。其获取配置的逻辑是:
1.获取指定应用的在本地仓库中的路径;
2.根据获取的本地位置作为搜索路径;
3.最后,获取到本地环境仓库中的配置信息。

其中,第一步的逻辑就变得极为重要了,因为这关乎获取的配置是否是最新的。在获取到Location之前,需要检查git仓库的状态,看一下代码中具体的实现。

	public String refresh(String label) {
		Git git = null;
		try {
			git = createGitClient();
			if (shouldPull(git)) {
				FetchResult fetchStatus = fetch(git, label);
				if(deleteUntrackedBranches) {
					deleteUntrackedLocalBranches(fetchStatus.getTrackingRefUpdates(), git);
				}
				// checkout after fetch so we can get any new branches, tags, ect.
				checkout(git, label);
				if (isBranch(git, label)) {
					// 将结果merge
					merge(git, label);
					if (!isClean(git, label)) {
						logger.warn("The local repository is dirty...");
						resetHard(git, label, LOCAL_BRANCH_REF_PREFIX + label);
					}
				}
			}
			else {
				// 如果没有更新,则直接checkout
				checkout(git, label);
			}
			// 返回Head Version
			return git.getRepository().findRef("HEAD").getObjectId().getName();
		}
		...
	}
	protected boolean shouldPull(Git git) throws GitAPIException {
		boolean shouldPull;//判断是否需要pull
		Status gitStatus = git.status().call();//获取远端git库的状态
		boolean isWorkingTreeClean = gitStatus.isClean();//状态是否有过提交
		String originUrl = git.getRepository().getConfig().getString("remote", "origin",
				"url");
		if (this.forcePull && !isWorkingTreeClean) {//强制拉取且有提交
			shouldPull = true;
			logDirty(gitStatus);
		}
		else {
			shouldPull = isWorkingTreeClean && originUrl != null;
		}
		if (!isWorkingTreeClean && !this.forcePull) {
			this.logger.info("Cannot pull from remote...");
		}
		return shouldPull;
	}

通过检查远端仓库的git状态,进而判断本地环境仓库是否需要刷新。#refresh依赖于#shouldPull的状态,当有新的提交时或者配置了强制拉取,git客户端将会fetch所有的更新,并merge到所在分支或tag,更新本地环境仓库。#refresh最终返回的是最新一次提交的HEAD Version。

多JGit仓库实现

Config Server中还可以配置多个Git仓库,服务启动时会自动读取这些配置属性,MultipleJGitEnvironmentRepository是JGit实现的子类。MultipleJGitEnvironmentRepository用以处理一个或多个Git仓库的环境仓储,其实现和JGit方式差异并不是很大。我们以其中的获取环境配置的#findOne方法为例,比较一下和之前的JGitEnvironmentRepository中实现的区别。

	@Override
	public Environment findOne(String application, String profile, String label) {		
		for (PatternMatchingJGitEnvironmentRepository repository : this.repos.values()) { // 1
			if (repository.matches(application, profile, label)) { // 2
				for (JGitEnvironmentRepository candidate : getRepositories(repository,
						application, profile, label)) {
					try {
						if (label == null) {  // 3
							label = candidate.getDefaultLabel();
						}
						Environment source = candidate.findOne(application, profile,
								label);
						if (source != null) {
							return source;
						}
					}
					// ...
				}
			}
		}

		JGitEnvironmentRepository candidate = getRepository(this, application, profile, label); // 4
		if (label == null) {
			label = candidate.getDefaultLabel();
		}
		if (candidate == this) { // 5
			return super.findOne(application, profile, label);
		}
		return candidate.findOne(application, profile, label);
	}
  1. 遍历所有的repos,MultipleJGit的实现中可能会有多个Git库;
  2. 通过应用名、profile和标签进行匹配,通过这三个参数指定了具体的应用;
  3. label标签为空的情况,设置默认的label为master;
  4. 通过应用名、profile和标签三个参数匹配不到Git仓库时,#getRepository方法没有列出,该方法则会判断repo中是否有占位符,并将占位符进行替换成实际的值,最后返回替换后的repo;
  5. 默认的git配置会执行到这一步,具体执行的是抽象SCM中的#findOne方法。

小结

本文主要介绍了 Spring Cloud Config 服务端 Config Server 中 JGit 方式实时获取配置信息的实现。Config Server 中还可以配置多个 Git 仓库, Spring Cloud Config 默认支持多仓库的配置读取。服务启动时会自动读取这些配置属性。接下来将会重点介绍多仓库的配置读取时,多个 repos 的匹配规则的实现。

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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