本文涉及的代码示例托管在github
https://github.com/CharlesMaster/EnvironmentPostProcessorDemo
https://github.com/CharlesMaster/PropertySourceLocatorDemo
背景
传统开发微服务开发中,我们通常是将系统的配置(数据库,缓存服务器)在application.properties中配置,但随着系统规模的扩大,项目成员增多,越来越多的人更改配置文件,开发、测试、生产环境分离,因配置产生的问题越来越多。
为了避免因配置文件的导致的问题产生,配置服务应运而生。在分布式系统中,配置中心是一个独立的服务部件,作用是专门为其他服务提供系统启动所需的配置信息,保证系统正确启动。
配置中心有哪些功能呢?
1.将配置统进行集中管理,提供一配置服务,开发、测试、生产环境均可直接从配置服务器中读取配置信息。大致就是,应用在启动后从配置服务器中获取配置信息,加入到环境中。这样所有的配置服务都可以进行集中管理。
2.追溯到配置变更的历史,诸如是谁在什么时候修改了哪些内容,根据这些信息进行配置回滚操作。
3.配置中心还能够增加权限管理,保证不同角色不同权限的人只能访问到可看的配置,防止重要线上配置信息的泄露。
4.基于配置中心的微服务非常适合多环境的打包,不用多次打包,而是一次打包。另外,其也是拥抱docker的,docker一次打包都得好几G,如果多套配置,那么就是多个docker镜像,极大浪费资源),基于配置中心的发布可以做到one jar,one docker,run everywhere。
案例
我们首先编写一个简单的springboot服务,对外提供接口访问内部配置文件。如下所示,我们提供了两个接口,分别访问我们application.properties的两个属性。
application.properties文件的内容如下:
和我们所期望的一样,我们访问http://localhost:8080/author和http://localhost:8080/city分别读取到了application.properties的内容
Spring boot中可以通过xml或者@ImportResource来引入本地的配置文件,且格式只能是 properties(或者 yaml)。
按照我们背景中所提的需求,我们需要通过远程配置中心替换掉application.properties的内容,用配置中心统一管理配置。那么该如何实现呢?笔者提供两个方案。
方案一 EnvironmentPostProcessor
EnvironmentPostProcessor接口官网是这么描述的
Allows for customization of the application's {@link Environment} prior to the application context being refreshed.
EnvironmentPostProcessor implementations have to be registered in
META-INF/spring.factories, using the fully qualified name of this class as the key.
EnvironmentPostProcessor processors are encouraged to detect whether Spring's
org.springframework.core.Ordered Ordered interface has been implemented or if the @org.springframework.core.annotation.Order Order annotation is present and to sort instances accordingly if so prior to invocation.
那我们就按照这份文档进行改造。
classpath定义一个META-INF文件夹然后在其下面先建spring.factories文件,在其中指定:
这时我们将application.properties的author属性注释掉
再进行访问时http://localhost:8080/author页面时,返回值已经变为了我们注入的Jack
强调,MyEnvironmentPostProcessor并不会覆盖本地属性,比如不注释author=Charles仍然返回Charles而不是Jack,如果实际生产撰写此类中间件需要优化该代码进行去重工作,也可以增加远端覆盖本地、本地覆盖远端的功能点
方案二 PropertySourceLocator
该方案的思路来源于 Spring Cloud Config。我们先看怎么操作:
首先编写MyPropertySourceLocator。
接着让其生效
最后再创建 META-INFO/spring.factories
我们可以看到,和EnvironmentPostProcessor不一样的地方是,在application.properties仍然如下的情况下,
http://localhost:8080/author 返回了Tom,http://localhost:8080/city仍然是Hangzhou
走得更远
本文只是一个DEMO,如果想撰写这样的中间件产品或者spring boot starter,可以从以下方面考虑:
1.设置全局开关,支持读取配置中心打开还是关闭功能
2.配置中心的健康检查
3.基于微服务的规范性管理
4.远程和本地配置覆盖的功能
5.分布式系统中,服务启动时,如果启用了分布式配置中心,则将从配置中心获取的配置进行备份。配置中心失效时,使用备份的配置文件启动服务。
源码解析
本文讲实战,没有过多讲原理,关于PropertySourceLocator和Spring Cloud Config的源码解析,我会在下一篇文章中更新,请关注本公众号,这里剧透一下,Spring Cloud Config就是采用我们方案二的思路去做的。
领取专属 10元无门槛券
私享最新 技术干货