我们之前做单体应用的时候是直接把配置写在 application.yml 中,但是如果是采用微服务架构的模式进行开发,这样的方式会存在哪些问题呢?首先维护困难、安全因素、更新配置时项目需要重启等等。针对这些问题,本文主要讲述的就是 Spring cloud config 这个组件,使用该组件可以很好的处理如下问题。
原始做法的缺陷
1、维护困难:假如一个服务,由多人开发,其中 A 在开发的时候,修改了配置,B 再来开发的时候,需要测试别的一些功能,这个时候配置文件已经被 A 修改得面目全非了,这就造成了冲突。
2、安全因素:而且处于安全因素考虑,公司项目线上的配置基本是不对开发公开的,特别是数据库的账号密码这种,基本是只有运维才知道,把配置放在项目里面的话,每个开发人员都能看到,这种情况就需要对配置文件进行隔离。
3、更新配置需要重启:线上更新配置是经常发生的事情,比如更新一点小小的配置,难道都需要重启吗?使用 spring cloud config 就可以解决这一点。
统一配置中心的架构
配置中心到时候也会作为一个服务,这些配置为了方便管理,我们都把它放到 git 上,使用 git 控制起来会比较方便。如下图所示,其中箭头代表数据流动的方向:
最开始是把配置放在远端的 Git,如 Gitlab,Github 或者自己搭建的私服,config-server 把配置从远端 Git 拉下来之后,放到本地 Git。config-server 与本地 Git 之间是双向流动的,既会把远端的 Git 放到本地中,假如远端 Git 不能访问了,也会从本地 Git 把配置拉出来,拿到配置之后,就可以给微服务模块来使用。shop 和 order 这两个服务,需要集成 config-client 这个组件。这就是统一配置中心整体的架构。
Config Server 端使用流程
1、引入相关依赖
因为 Config 配置中心也是作为一个 Client 服务注册到 Eureka Server 的,所以必须引入 Eureka Client 的依赖,作为一个 Eureka Client 注册到 Eureka Server 上面。作为统一配置中心,必不可少的引入 SpringCloud Config 组件的依赖:
1 | <dependencies> |
2、启动类加注解
在启动类上添加注解支持 @EnableConfigServer,其实不难发现很多 SpringCloud 组件的使用方式是一致的,都是先引入依赖,然后添加启动类的注解等流程,在这里不但需要 @EnableConfigServer 这个注解,同时不要忘记这也是一个 Eureka Client,所以 Eureka Client 的注解和配置也是必不可少的。
1 |
|
application.yml 配置文件:
1 | spring: |
3、配置文件放入仓库
不难发现,我们在上面的配置文件中配置了 Git 的仓库地址、用户名以及密码,因为从架构图可以看出,其他服务组件配置文件需要放在一个 Git 仓库中,可以是 Github、GitlabGit、Gitee 或者是自己搭建的 Git 私服。我演示的时候直接放在了 Gitee(码云)上面:
4、尝试访问配置文件
接下来可以尝试访问一下是否生效,开始 Eureka Server,然后启动统一配置中心注册到 Eureka Server 上面。
可以看到,虽然我们只是在 Master 分支上提交一个 order.yml,但是我们访问 order.yml 却无法访问,访问 order-a.yml、order-b.yml、order-a.properties、order-b.properties、order-a.json、order-b.json 却没有问题,也就是说 SpringCloudConfig 帮我们做了转换,那么具体的转换规则是什么呢?在日志里可以看到 /{label}/{name}-{profiles}.yml
的字样,这些分别代表的意义如下:
- label:Git 的分支,如 master、dev、test、pre-release 等等
- name:服务名称,在这里订单服务则为 order
- profiles:环境,比如测试环境、预上线环境、线上环境等
Config Client 端使用流程
1、引入 Config Client 依赖
1 | <dependency> |
2、修改配置文件
将 application.yml 修改为 bootstrap.yml,意思就是从指定的配置中心来获取配置文件,然后再执行启动 SpringBoot 的核心流程:
1 | spring: |
修改为 bootstrap.yml 后,也从原来的图表变成了一朵云,意思就是从服务器(统一注册中心)获取了
3、验证是否成功
在仓库中放置了 shop-test.yml 文件:
1 | server: |
还在仓库中放置了 shop-dev.yml 文件
1 | server: |
两个配置文件的 env 属性不同,写一个 Controller 测试一下从统一配置中心拿到的配置文件的内容:
1 |
|
当我们把 bootstrap.yml 中的 profile 属性设置为 dev 的时候,拿到的配置文件就是 shop-dev.yml,此时访问打印环境属性的接口打印出来就是 dev;当我们把 bootstrap.yml 中的 profile 属性设置为 test 的时候,拿到的配置文件就是 shop-test.yml,此时访问打印环境属性的接口打印出来就是 test:
统一配置中心的高可用
在配置 Eureka 的高可用时,采用了相互注册的方式来实现高可用性。统一配置中心服务的高可用其实很简单,因为统一配置中心也 Eureka 的客户端,所以只要拥有足够的统一配置中心实例向 Eureka Server 注册即可实现高可用。由于是在本地开发环境,所以通过指定不同的端口号的方式来启动三个统一配置中心的实例:
1 | -Dserver.port=8080 |
在 Eureka Server 的界面可以看到,三个配置中心的实例已经注册到了 Eureka Server 上面:
使用配置中心的注意点
http://localhost:8761/eureka/
这个地址是默认的地址,假设我们改成其他的端口或者其他的 IP 地址就会报错找不到 Eureka,其实要理解这一点并不难,因为要拿到配置文件的前提是得先找到统一配置中心的实例,统一配置中心的实例的前提是你得去 Eureka Server 上面找,前提是自身得注册到 Eureka Server,但是此时并没有配置 Eureka Server 的注册地址,所以相当于与世隔绝是一个孤立的模块,自然会发生启动失败,所以关于 Eureka Server 的配置,无需由统一配置中心来分发,而是直接写在配置文件里即可。
当然还有一种方式,那就是指定统一配置中心的 URL,这样就能直接找到统一配置中心的实例,在 bootstrap.yml 中:
1 | spring: |
总结一下就是:
- 方式一:先找到统一配置中心,获取配置,从配置中心给的配置中找到 Eureka Server,再注册到 Eureka Server
- 方式二:先找到 Eureka Server,从 Eureka Server 找配置中心,从而获取对应的配置(推荐做法)
另外还有一点需要注意,那就是如果你需要的配置文件是 shop-dev.yml,Git 仓库同时存在 shop.yml 与 shop-dev.yml,那么统一配置中心在拉取配置文件的时候,会把 shop.yml 和 shop-dev.yml 两个文件同时拉取下来,并且进行内容合并,所以我们通常遵循如下原则,那就是公共的配置内容写在 shop.yml(对于本例而言)中,不同环境的配置内容写在 shop-dev.yml 或者 shop-test.yml 中。