写在前面

在前面我们成功的搭建起一个具备基本结构的配置管理服务端和客户端,也学习了一些基本的配置,接下来将进一步深入学习Spring Cloud Config中有关服务端的知识。

基础架构

在学习服务端相关配置信息之前,先复习一下之前搭建的入门例子中使用的基础架构,如下图所示:

接下来好好分析一下上述架构,可以看到里面包含4种组件,5个元素,相关的分析如下所示:

  • 远程Git仓库:用于存储配置文件,一般自己学习可以使用GitHub或者Gitee,公司一般会基于GitLab搭建属于自己的Git服务器。这里存放的就是针对应用名为config-server,但是application名为envy的多环境配置文件:envy-{ profile }.yml。
  • Config Server分布式配置中心:即此处构建的分布式配置中心(项目名称为config-server),里面配置了所要连接的Git仓库的位置、账户、密码等信息。
  • Config Server本地Git仓库:在Config Server的文件系统中,每次客户端请求获取配置信息时,Config Server从Git仓库中获取最新配置到本地,然后在本地Git仓库中读取并返回。当远程仓库无法获取时,直接将本地内容进行返回。
  • Service-A和Service-B:这些都是具体的微服务应用,它们中配置了Config Server的地址,这些应用在启动的时候,会向Config Server请求获取自己需要的配置信息。

    获取配置信息流程

    接下来分析客户端应用从配置管理中获取配置信息时的执行流程:
    (1)客户端应用启动时,会根据bootstrap.properties配置文件中配置的应用名{ application }、环境名{ profile }、分支名{ label }、Config Server地址等信息,向Config Server请求获取配置信息:

(2)Config Server根据自己维护的Git仓库信息和客户端传递过来的配置定位信息去查找配置信息:

(3)通过git clone命令将找到的配置信息下载到Config Server的文件系统中。

(4)Config Server创建Spring的ApplicationContext实例,并从Git本地仓库中加载配置文件,最后将这些配置内容读取出来返回给客户端应用。

(5)客户端应用在获得外部配置文件后加载到客户端的ApplicationContext实例,该配置内容的优先级高于客户端Jar包内的配置内容,所以在Jar包中重复的内容将不再被加载。

也就是说其实Config Server就是通过git clone命令将配置信息存于本地,起到了缓存的作用,这样即使Git服务端无法访问时,依然可以从Config Server中的缓存中取出所需数据。

Git配置仓库

Spring Cloud Config服务端配置仓库默认使用了Git,因为它非常适合存储配置内容,且可以使用各种第三方工具来对其内容进行管理更新和版本化,更重要的是Git仓库的Hook功能还可以帮助我们实时地监控配置内容的修改。同时Git本身就自带了版本控制功能,这就意味着使用Git进行存储,一个应用的不同部署实例可以从Spring Cloud Config的服务端获取不同的版本配置,这在一些特殊场景下非常实用,如需要同时测试多个环境的时候。

既然Spring Cloud Config默认使用了Git,那么对于Git的配置又是怎样的呢?其实很简单,只需在Config Server配置中心的application.properties配置文件中通过以下参数来实现:

1
2
3
4
5
# Git仓库地址、仓库下的子目录、用户名、密码
spring.cloud.config.server.git.uri=https://github.com/licheetools/springcloud_test.git
spring.cloud.config.server.git.search-paths=config-repo
spring.cloud.config.server.git.username=username
spring.cloud.config.server.git.password=password

一般在开发阶段,为了快速调试都会将这个Config Server配置中心以本地仓库的方式进行运行,只需将uri改成以file://为前缀即可(windows系统需要使用file://来定位文件内容):

1
spring.cloud.config.server.git.uri=file://${ user.home }/config-repo

其中的${ user.home }表示当前用户的所属目录,请注意使用file://配置的本地文件系统方式虽然对于本地开发测试时非常方便,但是也仅仅是用于开发和测试,在生产环境中务必使用自己的Git仓库来存储配置资源。

占位符配置URI

为什么需要学习使用占位符来配置URI呢?举一个非常简单的例子,假设现在有两个应用,这两个应用对应的配置文件地址分别为https://github.com/licheetools/mycode-servicehttps://github.com/licheetools/mycode-service-config,可以看到后者仅仅是在前者的尾部添加-config作为后缀来作为仓库名称,那么问题来了,我们只有一个Config Server,当这两个应用都去访问Config Server时,此时Config Server应当去哪个地址来获取配置文件呢?如果学了URI这将是一个简单的事,可以使用URI来实现通用的仓库配置。

在前面我们就已经接触到Spring Cloud Config中的三个占位符:{ application }、{ profile }和{ label },其实它们除了用于标识配置文件的规则,还可以用于Config Server中对Git仓库地址的URI配置,此时它们的含义如下所示:

  • { application }表示应用名。当客户端向Config Server发起获取配置请求时,Config Server会根据客户端bootstrap.properties文件中配置的spring.application.name参数来填充{ application }这一占位符,用来定位配置资源的存储路径,也就是根据微服务应用的属性来动态获取不同位置的配置:

  • { profile }表示使用环境。这个映射到客户端中配置的spring.cloud.config.profile参数,用来指定使用的环境。

  • { label }表示服务器上仓库的分支。这个映射到客户端中配置的spring.cloud.config.label参数,用来指定服务器上仓库对应的分支版本。需要注意的是,如果Git的分支和标签名包含/,那么{ label }参数在HTTP的URL中应该使用(_)来替代,以避免改变了URI的含义,指向到其他的URI资源。

那么上面例子中对于https://github.com/licheetools/mycode-servicehttps://github.com/licheetools/mycode-service-config,则可以使用spring.cloud.config.server.git.uri= https://github.com/licheetools/{application}-config来配置,这样就可以同时匹配多个不同服务的配置仓库。

配置多个仓库

Config Server功能非常强大,除了可以通过application和profile模式来匹配配置仓库外,还支持通过带有通配符的表达式来匹配,以实现更为复杂的配置需求。当我们有多个匹配规则的时候,还可以使用逗号来分割多个{ application }/{ profile }配置规则。举个例子,如下所示的配置信息:

1
2
3
4
5
6
spring.cloud.config.server.git.uri=https://github.com/licheetools/config-repo
spring.cloud.config.server.git.repos.dev.pattern=dev/*
spring.cloud.config.server.git.repos.dev.uri=file://home/git/config-repo
spring.cloud.config.server.git.repos.test=https://github.com/test/config-repo
spring.cloud.config.server.git.repos.prod.pattern=prod/pp*,online/oo*
spring.cloud.config.server.git.repos.prod.uri=https://github.com/prod/config-repo

上述配置内容通过使用spring.cloud.config.server.git.uri属性指定了一个默认的仓库https://github.com/licheetools/config-repo,当开发者使用{ application }/{ profile }模式未能匹配到合适的仓库时,就将在该仓库位置下获取配置信息。与此同时我们还配置了三个仓库,分别是dev、test和prod。其中的dev仓库匹配dev/*的模式,所以无论profile是什么,它都能匹配application名称为dev的应用。并且我们可以看到它存储的配置文件位置还采用了Config Server的本地文件系统中的内容。对于此配置,我们可以通过访问http://localhost:4001/dev/profile的请求来验证到该仓库的配置内容,其中profile可以是任意值。而test和prod仓库则均使用了Git仓库的存储,并且test仓库未配置匹配规则,所以它只匹配application名为test的应用;prod仓库则需要匹配application为prod且profile为pp开头,或者application为online且profile为oo开头的应用和环境。

需要注意的是,当配置多个仓库的时候,Config Server在启动的时候会直接克隆第一个仓库的配置库,其他的配置库只有在请求时才会被克隆到本地,所以对于仓库的排列可以根据配置内容的重要程度来进行区分。还有如果表达式是以通配符开始的,那么需要使用引号将配置内容引起来。

子目录存储

在前面我们在配置文件中除了配置spring.cloud.config.server.git.uri以外,还配置了一个spring.cloud.config.server.git.search-paths参数,通过该参数我们实现了在https://github.com/licheetools/springcloud_test.git仓库下的config-repo子目录下实现配置的存储。

其实对于spring.cloud.config.server.git.search-paths参数的配置也是可以使用{ application }、{ profile }和{ label }占位符,举个例子来说:

1
2
spring.cloud.config.server.git.uri=https://github.com/licheetools/springcloud_test.git
spring.cloud.config.server.git.search-paths={application}

通过上面的配置,我们可以实现在https://github.com/licheetools/springcloud_test.git仓库中,一个应用对应一个目录的目的。

访问权限

Config Server在访问Git仓库的时候,若采用HTTP的方式进行验证,那么需要在配置文件中增加username和password属性来配置账号,之前我们就是这样配置的:

1
2
3
4
spring.cloud.config.server.git.uri=https://github.com/licheetools/springcloud_test.git
spring.cloud.config.server.git.search-paths=config-repo
spring.cloud.config.server.git.username=username
spring.cloud.config.server.git.password=password

如果开发者不选择使用HTTP的认证方式,也可以采用SSH的方式,通过生成Key并在Git仓库中进行配置匹配以实现访问,这种方式也是可以的。

SVN配置仓库

Config Server除了支持Git仓库外,还支持SVN仓库,而且使用起来也较为简单,只需如下两个步骤:

第一步,在pom.xml配置文件中添加svn的依赖,使Config Server拥有读取SVN内容的能力:

1
2
3
4
5
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit</artifactId>
<version>1.8.10</version>
</dependency>

第二步,在application.properties配置文件中新增SVN的配置属性,用于指定SVN服务器的地址和访问的账户名称、密码,如下所示:

1
2
3
spring.cloud.config.server.svn.uri=svn://localhost:443/envythink/config-repo
spring.cloud.config.server.svn.username=username
spring.cloud.config.server.svn.password=password

通过上面的配置修改,Config Server就可以使用SVN作为仓库来存储配置文件了,而对于客户端来说,这个过程就是透明的,所以不需要做任何变动。

本地仓库

在使用了Git或者SVN仓库之后,文件都会在Config Server的本地文件系统中存储一份,这些文件默认会被存储于config-repo为前缀的临时目录中,如名为/tmp/config-repo-<随机数>的目录。由于这个名称中包含了随机数且这是一个临时目录,所以可能会带来一些未知的问题,因此比较好的做法是指定一个固定的位置来存储这些较为重要的信息,可以使用spring.cloud.config.server.git.basedir或者spring.cloud.config.server.svn.basedir参数来配置本地专门存放这些文件的目录。

本地文件系统

使用本地仓库的确可以减少对线上仓库的依赖,但是最好的方式就是不使用Git或者SVN仓库的存储,而是使用本地文件系统的存储方式来保存配置信息。那么如何实现这个目的呢?其实操作非常简单,只需两步即可:

第一步,在application.yml配置文件中使用spring.profiles.active=native参数来启用本地环境,这样Config Server就会从应用的src/main/resource目录下搜索配置文件。

第二步,如果用户需要指定搜索配置文件的路径,则可以使用spring.cloud.config.server.native.searchLocations参数来指定具体的配置文件位置。

请注意,虽然Spring Cloud Config提供了本地文件系统这一功能,但是为了更好的支持内容管理和版本控制等强大功能,还是推荐使用Git仓库的方式。