配置其实分为结构和内容两个方面,结构对应的是代码,比如1.0.0新开发的代码上有一个功能开关 ${feature.switchA}
,但master上还没有,这就是结构的变化。另一方面是内容,1.0.0的开发分支有两个测试环境,连着不同的数据库,那么对应的 ${mysql.url}
的内容肯定不同。
内容的类别上也可以分为三种:业务配置,功能开关,服务配置。
Spring Cloud的配置中心是Spring Config,经过两年的使用,发现了其中不少的问题,有些是使用问题,有些是Spring Config本身的管理能力导致的问题。
Spring Config首推基于git的管理方式,提供了两个管理维度,一个是label(即branch),一个是profile。当服务foo在一套代码下要安装多套环境,比如预发布环境有2套,一套在shanghai机房,一套在beijing机房。那么比较自然的管理维度就是利用profile,foo-shanghai.yaml以及foo-beijing.yaml。当生产环境也依然需要2台时,怎么处理呢?这时候就会有两种做法,一种利用增加label维度做区分,一种依然只用profile。
Name | Branch | Profile |
---|---|---|
foo-shanghai.yaml | stg | shanghai |
foo-beijing.yaml | stg | beijing |
foo-shanghai.yaml | prd | shanghai |
foo-beijing.yaml | Prd | beijing |
branch其实表示的是结构,即对应不同的代码,而profile对应的是内容。
这种方式有什么问题?一般应用都是只有profile来区分环境,比如logback要分环境区分配置也是通过 <springProfile>
来指定。一旦采用两个维度来确定唯一的配置,那么所有项目都需要有 label
这个变量。
试想如果foo这个应用在线上有个bug需要fix,势必会增加一个hotfix的branch在配置中心,同时还需要增加相应的profile,对应foo的 label
变量设置为hotfix, profile
设置为beijing或者shanghai。
再考虑另一种情况,foo在prd的代码需要放到stg进行验证如何处理?foo的代码版本肯定是prd的(因为stg的配置结构也许已经变了),但profile需要用stg的环境。这时实际上只能在配置中心的prd分支上新建一个新的profile来临时满足这种需求。
Name | Branch | Profile |
---|---|---|
foo-stg-shanghai.yaml | master | stg-shanghai |
foo-stg-beijing.yaml | master | stg-beijing |
foo-prd-shanghai.yaml | master | prd-shanghai |
foo-prd-beijing.yaml | master | prd-beijing |
这种方式可以降低管理维度,即放弃label的维度,只有profile的维度。同样的问题,如果foo这个应用在线上有个bug需要fix,那么需要新增两个profile,hotfix-beijing和hotfix-shanghai。虽然维度降低了,但是管理上却有些麻烦。因为master的这个分支无法保护起来,如果有开发人员直接修改了prd-XXX的环境就会导致线上问题。
同样的,foo在prd的代码需要放到stg进行验证如何处理?foo的代码版本肯定是prd的(因为stg的配置结构也许已经变了),但profile需要用stg的环境。这时实际上只能再配置中心新建一个profile,比如stg-oldshanghai,来满足这种需求。
然而我们知道,增加新的profile其实还是挺麻烦的事情,如果代码中有直接比较profile的逻辑,那么往往容易出现问题。
有没有不临时增加profile的办法呢?其实仔细思考一下,在stg环境验证prd的服务,真正的逻辑是什么?是希望用stg环境的配置内容,以及stg某个历史版本(与prd匹配的)的配置结构。所以纵向维度我们需要的其实是version,profile都是stg-shanghai,而version一个是1.0.0,一个是latest。
好了,现在我们来综合一下两种方式,可以使用git的分支作为version,profile依然还是按照方法二来区分。毕竟频繁增加环境的可能性不高。但是如果要同时维护一个profile两个分支,其实还是要来回切换的,比较麻烦,这也是Spring Config为人诟病的管理功能弱。好在Spring Cloud也支持mysql,用mysql同时管理多个label的内容还是方便不少,只是git自带的“后悔药”(history)功能没有了。所以说还是有利有弊。
如果想要更完善的配置管理工具,建议还是使用Apollo。要想用好Spring Cloud,必须可以忍受它比较弱的管理能力,并且做好前期规划,结合项目特点来使用label和profile的能力。