转载

Java开发从入坑到入沟—多云环境的配置文件管理

Spring 提供了一套代码多环境运行的基本解决方案。

通过application-xxx.yml,辅助启动时指定xxx环境,使得不同环境可以拥有独立的配置内容。 例如

java -jar xxx.jar --spring.profiles.active=xxx
复制代码

然而现实总是比hello world残酷的多。

Java开发从入坑到入沟—多云环境的配置文件管理

配置文件地狱

目前我们有3套研发环境,差不多9套生产环境。据我推测,生产环境的数量还会不断增加。

让我花点时间来解释一下哪里弄出来这么多生产环境:snowman:️

  1. 我们最初的一套生产环境在阿里云(初号机)。
  2. 后来一波腾讯系客户说他们使用的saas产品必须运行在腾讯云上。于是我们多了一套腾讯云生产环境。
  3. 好消息!我们拓展了新加坡客户,成立了新加坡销售中心,但是新加坡的销售抱怨访问国内阿里云环境的速度太慢了,他们需要一套新加坡本地的环境。于是我们又多了一套马来云生产环境。
  4. 我们连续接了两家体量非常大的客户,这两家客户都希望他们可以各自独占一套云环境。于是我们阿里云上又多了两套生产环境。
  5. 百度云和我们公司开始洽谈商务合作,希望我们将客户导流到百度云,老板答应后,我们又多了一套百度云生产环境。
  6. 华为云和百度云类似,也希望和我们有商务合作。老板可能觉得不能厚此薄彼,于是我们又多了一套华为生产环境。
  7. 日本客户说他们只允许使用aws的云服务器。所以我们又多了一套aws生产环境。
  8. 我们的saas服务终于要登录钉钉市场了,钉钉云和阿里云无法互通,我们毅然又增加了一套钉钉云生产环境。

所以最后我们的配置文件变成了这样 :information_desk_person:‍♂️

Java开发从入坑到入沟—多云环境的配置文件管理

你大概觉得好像还能接受,毕竟生产环境不是天天增加,虽然看起来确实丑丑的。

真棒,你是个乐观的人,和我一样!

Java开发从入坑到入沟—多云环境的配置文件管理

微服务改变了这一切

我们拆了差不多30个左右的服务,现在每个服务都要维护12个application-xxx.yml的配置文件。

很好!我们现在要维护差不多30*12=360个配置文件了!(其实还有360个logback配置文件 ‍♂️) 随着服务数量和环境数量的增加,配置文件会以n^2的速度增加。

我们的运维大兄弟根本不管研发死活,他反正是快活不下去了。

Java开发从入坑到入沟—多云环境的配置文件管理

如此多的配置文件真的让人心力交瘁。每次新增一套环境,运维大兄弟都要跟这30个服务的owner详细确认每个配置项的值,比如数据库地址啦,redis端口啦,是否启用本地存储啦……(每个配置文件平均有10个左右的配置项,而大部分配置项都是服务owner定义的,运维大兄弟并不知道是什么意思)

万一有个公用的配置需要改动(比如数据库地址需要由公网地址改成内网地址),运维大兄弟又要跪求这30个服务的owner,让他们把每个服务的配置文件都改一遍。

每次新增环境这种修改可能反复多次。

我觉得运维大兄弟已经精神分裂了,服务owner们也心力交瘁。

这一切真是妙不可言 :full_moon_with_face:

救救孩子

我们终于忍无可忍了。

服务owner和运维大兄弟的解耦

仔细想想,每套环境变化的配置就那几个,数据库,redis,elastic,域名。其他配置基本是不变的。

而这些变化的东西,服务owner可以不用知道,只要运维大兄弟清楚就可以了!

于是,我们尝试做了两层配置文件:将所有配置,根据服务owner与运维大兄弟的知识领域不同,切分到了2个不同的配置文件中。

服务配置文件

服务相关的配置,比如是否启用redis缓存,文件存储路径,是否启用邮件通知等等。这个配置文件的特点,就是只有服务owner知道这些配置是什么意思,运维大兄弟并不清楚里面的配置项的含义。通常这个配置文件的内容无需根据不同环境区分。比如某个服务在A环境没有启用邮件通知,那么这个服务在各个环境都不会启用邮件通知。

这个配置文件由服务owner自己维护在application.yml默认配置文件中。

资源配置文件

资源相关配置,比如数据库地址,redis地址,端口,es地址,oss地址等等。 这个配置文件的配置项非常固定(因为用到的资源就那么几个)。其特点是只有运维大兄弟知道怎么配置,配置值随着不同环境改变。

把它俩结合起来

服务配置文件直接定义在application.yml中,这个默认配置文件通过引用固定的 资源配置变量 (数据库地址,redis地址端口等等),从而和资源配置文件对接。

举个例子,所有30多个服务都可以在application.yml中通过

${db.host}
复制代码

获取数据库地址。

比如panda服务可以这样配置自己的数据库地址:

spring.database.url=${db.host}/panda&encoding=utf8
复制代码

我们做了什么?现在每个服务都有了2类配置文件,看起来配置文件数量变得更多了!

不过仔细想想,其中服务配置文件是无需跟随环境变更,只有资源配置文件会随环境改变。

让我们看看目前为止,发生了哪些变化。

  1. 由于各个服务引用的资源地址都是相同的(比如数据库host,redis host等等),每次新增环境时,运维大兄弟需要为新环境准备一个资源配置文件,然后把这个文件发给所有服务owner,要求他们把这个资源配置文件加入到自己服务的代码中。在这个配置文件中,运维大兄弟只要维护一些基本的数据库地址,redis地址等资源相关配置就可以了,这些概念都是他熟知的。

  2. 对于服务owner而言,变化似乎更加明显。新增环境时,运维大兄弟不会不停地和自己沟通每个配置的值是什么了,而是直接丢过来一份资源配置文件,类似application-resource-dev.yml,要求每个服务owner打包在程序里。服务owner甚至不需要关心里面放了哪些东西。

  3. 运维大兄弟启动服务时,会指定服务所对应的资源配置文件,比如这样

java -jar xxx.jar --spring.profiles.active=resource-dev
复制代码

配置文件的拆分,使得服务owner和运维大兄弟解耦了!

Java开发从入坑到入沟—多云环境的配置文件管理

引入nacos配置中心

这30多个服务引用的资源配置文件内容都是一样的,那么能否把这30个相同的配置文件从代码里抽离出来呢?

我们终于想到了nacos。

这是入沟系列不是入坑系列,nacos基本概念就不讲了。

我们现在要做的是,把这30多个服务共用的资源配置文件,维护到nacos配置中心,并让这些服务指向nacos就可以了!这非常简单!

让我们看看引入nacos后,发生了什么变化。

  1. 每次新增环境时,运维大兄弟需要在nacos中,维护一个资源配置文件,比如resource-dev.yml. 在资源文件中定义各类资源的主要信息,而无需再和服务owner有任何交流。甚至未来新增服务,运维大兄弟也可以不用关心,因为每个服务都会按照约定来读取资源配置。

    启动服务时,运维大兄弟只要在启动命令中指明启动配置文件的名字,服务就会自动去nacos读取对应资源配置文件的值,例如

java -jar xxx.jar --spring.profiles.active=resource-dev
复制代码
  1. 对服务owner而言就更加美妙了,新增环境不需要他们做任!何!事!情!

    他们只需要在application.yml中,按约定读取资源配置的值,并使应用启动时连接到nacos配置中心就可以了。而这些只是一次性的工作!一劳永逸!新增环境再也不需要各个服务owner做任何事情了。这一切简直太棒了!

每个的服务配置文件变成了这样

Java开发从入坑到入沟—多云环境的配置文件管理
Java开发从入坑到入沟—多云环境的配置文件管理

#技术管理/环境管理 #Java开发从入坑到入沟

原文  https://juejin.im/post/5eb16e8de51d45216c564646
正文到此结束
Loading...