alibaba / spring-cloud-alibaba

Spring Cloud Alibaba provides a one-stop solution for application development for the distributed solutions of Alibaba middleware.
https://sca.aliyun.com
Apache License 2.0
27.42k stars 8.17k forks source link

[discuss]: nacos config support sharing configuration with multi Applications #141

Closed pbting closed 3 years ago

pbting commented 5 years ago

SCA Nacos Config 共享配置方案设计

随着社区的回馈,发现 Spring Cloud Alibaba Nacos Config Starter 目前不能完美的来支持多个应用间的一些共享配置。 在实际的业务场景中应用和共享配置间的关系可能如下图所示:

应用的配置关系

目前 SCA Nacos Config 可以灵活的支持单个应用间在多套环境可灵活的切换,但是在多个应用间共享一些通用的配置支持的还不是很完美。 本方案设计的目标就是来解决这个问题。目前有三种设计方案,分别是:

下面分别来分析三种方案的具体实现和优缺点。

基于域名的配置方式给应用分组

通过一个配置参数(例如:${spring.application.group}) 来指明当前应用所属的分组(或者说所属的域)。 例如我有两个应用分别为Order_Application和Auth_Application,给这两个应用配置的分组名(域)是:

spring.application.group=com.alibaba.aliware.edas

那对于Spring Cloud Alibaba Nacos Config 来说,多个应用可以属于 com.alibaba 这个应用分组(域),也可以属于 com.alibaba.aliware 这个应用分组(域),当然也可以属于 com.alibaba.aliware.edas 这个应用分组(域)。 罗里吧嗦了这么多,目的就是 Data Id 通过以这个分组(域)来命名,从而实现多个应用间在某个分组(域)下的共享配置。如下图所示:

多应用间的配置关系

以这种方式来实现多个应用间的配置共享,可以看出他具有天然的局限性。

当然他的好处也非常明显,当你理解了他背后的设计理念时,这个共享配置的层次也非常明显。因为层次的关系天然依托于域名的层次关系。

自定义的方式来命名 Data Id

这种方式实现简单易懂,即 SCA Nacos Config 会新增加一个配置,用来配置可实现共享配置所有的 Data Id。如下所示:

spring.cloud.nacos.shared.dataids=global.yaml,app-common.yaml,app-local-common.yaml

NOTE: 为了尽可能的和Nacos使用方式(即Data Id 是一个带有额外文件扩展名的)保持一致,这里配置的Data Id 是一定需要带上文件扩展名的。

这个时候两个应用(或多个应用)之间共享配置的 Data Id 关系如下图所示:

Spring Boot 提倡约定大于配置。当使用这种方式来实现应用间的共享配置时,我们也继承了Spring Boot的这个优良传统,多个共享配置间的一个优先级的关系我们约定:按照配置出现的先后顺序,即后面的优先级要高于前面的。 这种方式的优点在于:

当然这种方案的缺点在于扩展性不强。即如果对于某个共享配置需要做额外的配置,例如额外配置Group/是否需要刷新/是否需要从本地缓存加载等等。因此为了应对这种类型的场景,小组内讨论出了第三种方案。

通过类似面向对象方式的自定义配置

说明: Spring 可以支持在加了 ConfigurationProperties 注解配置类的内部某个对象实例来注入应用中的一些配置。

这种使用方式查了一下官方和网络上没有一个大的标题总结,结合这种方式很像给某个实例中的字段赋值,所以这里先暂时取名: 类似面向对象方式的自定义配置(有更好能够形象的标明其含义的命名可以在下面留下评论-_-)。

这种方案沿用了第二种设计方案的优点,同时又弥补了第二种方案的不足。我们通过内部定义一个对象,来支持一些灵活的扩展配置。 我们给这个对象可以预留一些可扩展的配置字段。例如:

public class Config{
    private String dataId;
    private String group = "DEFAULT_GROUP";
    private Boolean refresh = false;
    //.....后期可能还有其他的一些配置

    //省略 set/get 方法
}

最终在实现时是可以支持以list的方式来配置其值。如下是两个扩展配置的实例:

spring.cloud.nacos.config.ext-config[0].data-id=global-shared.properties # group 和referesh 使用默认值
spring.cloud.nacos.config.ext-config[1].data-id=app-common.properties
spring.cloud.nacos.config.ext-config[1].group=DEVELOP_GROUP #配置自定义所在的组
spring.cloud.nacos.config.ext-config[1].refresh=true #需要刷新

NOTE: 为了尽可能的和Nacos使用方式(即data id是一个带有额外文件扩展名的)保持一致,这里配置的dataid是一定需要带上文件扩展名的。

最终的实现

SCA Nacos Config 在第二种方案和第三种方案的实现上是并存的。如果你觉得第三种方案配置的比较麻烦,同时第二种方案就可以满足你的需求,这个时候就可以选择第二种方案。 如果你需外可读性好、层级感比较明显、后期的扩展性更强,那这个时候第三种方案也是OK的。

qiumingbao commented 5 years ago

第二种方式可读性更好,同时通过手工指定,可以灵活控制不同版本之间配置共存的情况。第三种方式略复杂,同时会否影响性能。

fudali113 commented 5 years ago

我认为是不是有一种可以在配置在增加相关配置的功能,比如可能因为一些原因我需要给我的信用添加相似的配置,但是它可能也是比较独立的一块。

如果这个样子我们增加一个文件,然后在去项目里面增加一个这个文件的配置,这样子项目多了修改的成本就会比较高。

那是不是在我们项目dataid指定的配置里添加某种还可以再加载一次外部配置的功能,我们就可以在外部有一个统一修改的地方。这样子会不会带来更方便的扩展性?

universefeeler commented 5 years ago

比较支持第一种方式,在应用较多的时候优势明显;另外,层次性更好,合理命名会具备很强的自解释性;另外更符合一般通用配置思维

pbting commented 5 years ago

第二种方式可读性更好,同时通过手工指定,可以灵活控制不同版本之间配置共存的情况。第三种方式略复杂,同时会否影响性能。

第三种方式相对于第二种来说确实稍微复杂了那么一点。但是性能的话 可以具体说下哪里会影响到性能?我理解这里只是表现形式上的不一样,做监听取数据都是一样的,同时这也是在应用启动的时候执行。所以没太明白你指的会影响性能是指?

pbting commented 5 years ago

我认为是不是有一种可以在配置在增加相关配置的功能,比如可能因为一些原因我需要给我的信用添加相似的配置,但是它可能也是比较独立的一块。

如果这个样子我们增加一个文件,然后在去项目里面增加一个这个文件的配置,这样子项目多了修改的成本就会比较高。

那是不是在我们项目dataid指定的配置里添加某种还可以再加载一次外部配置的功能,我们就可以在外部有一个统一修改的地方。这样子会不会带来更方便的扩展性?

我理解下来你的意思是不是希望可以加载只要匹配 application-*.properties 类型的data id 都可以动态加载。那这个时候再加一个 这种类型的配置就不要手动的去应用配置文件中指定需要加载的dataid了, 是吗?

pbting commented 5 years ago

比较支持第一种方式,在应用较多的时候优势明显;另外,层次性更好,合理命名会具备很强的自解释性;另外更符合一般通用配置思维

同意楼主上面的观点,但是他的局限性也是比较明显,限制比较多。

fudali113 commented 5 years ago

我认为是不是有一种可以在配置在增加相关配置的功能,比如可能因为一些原因我需要给我的信用添加相似的配置,但是它可能也是比较独立的一块。 如果这个样子我们增加一个文件,然后在去项目里面增加一个这个文件的配置,这样子项目多了修改的成本就会比较高。 那是不是在我们项目dataid指定的配置里添加某种还可以再加载一次外部配置的功能,我们就可以在外部有一个统一修改的地方。这样子会不会带来更方便的扩展性?

我理解下来你的意思是不是希望可以加载只要匹配 application-*.properties 类型的data id 都可以动态加载。那这个时候再加一个 这种类型的配置就不要手动的去应用配置文件中指定需要加载的dataid了, 是吗?

应该有一些差别,我不希望通过范匹配来进行一个数据的拉取,我希望所有的配置拉取都是明确的,这也是我不太认可第一种方案的原因之一;

我的意思大概是这个样子的: 比如我的应用配置是这个样子的:

spring.cloud.nacos.shared.dataids=global.yaml,app-common.yaml,app-local-common.yaml

然后我的app-common.yaml 配置是这个样子的:

include-dataids:
- xxx.yaml

那么最终 xxx.yaml 也会加载成为我应用的配置,xxx.yaml的优先级比 include 他的配置文件(app-common.yaml) 优先级略低,但是优先级高于基础配置中比 app-common.yaml 优先级更低的配置 global.yaml ;

所有的 dataId 都是必须手动制定的,虽然范匹配和基于一定规则匹配会带来一定的遍历性,但是也可能在某些时候带来一定的不确定性(比如配置的人还不太熟悉该规则?或者是一时忘记了某种规则?)

更简洁一些的方案

同时,以上只是基于第二种方案提出的,在于优先级的处理上可能会有些复杂,那是不是也可以简单点的定义为在应用基础配置中只能配置一个 dataId: app-local-common.yaml,然后在 app-local-common.yaml 中去做 include 的操作?

想法的来源

我的方案大致来自于我的两个对于配置中的诉求:

@pbting

pbting commented 5 years ago

include-dataids

恩有道理。这个方案算是相对于第二种和第三种的一个补充。即在dataid 暴露出来给业务方自己配置的同时,又支持在配置里面显示的说明需要 include-dataids。那这个时候就我理解就相当于在你们的配置里面需要指明SCA Nacos Config 能够识别的一个 key,才可以去加载。

可以给我们提个feature。

fudali113 commented 5 years ago

怎么提 feature 啊? 再开一个 issue ? @pbting

pbting commented 5 years ago

怎么提 feature 啊? 再开一个 issue ? @pbting

是的,issue 开头用 [feature] 标明即可。感谢..

xujingle1995 commented 5 years ago

请问各位大佬,第一种“基于域名的配置方式给应用分组”,为什么我配置了spring.application.group=com.alibaba.aliware.edas,在nacos server创建了com.alibaba:application.properties/com.alibaba.aliware:application.properties/com.alibaba.aliware.edas:application.properties三个配置文件,然而并不起效果?工程启动依然会去nacos上寻找${spring.application.name}.properties,找不到就直接报错?group和命名空间都没问题。我用的0.2.1.RELEASE版本的,Nacos Server 0.7.0版本

gumutianqi commented 5 years ago

请问目前Nacos 的实现情况是怎么样的呢,求应用共享配置 example project.

KoumiArt commented 4 years ago

多个namespace之间,无法实现共享啊?

KoumiArt commented 4 years ago

@pbting

lxhcn commented 4 years ago

不知道以前是怎么样的,但是现在第二种的配置应该是有些问题的吧

spring.cloud.nacos.shared.dataids= 应改为 spring.cloud.nacos.config.shared-dataids=

mushanzi1216 commented 4 years ago

同问现在是如何实现的

sdaduanbilei commented 4 years ago

不可以夸 namespace 共享

robints commented 4 years ago

namespace的配置限制是200个,如何解决跨namespace共享配置的问题?

ynfatal commented 3 years ago

不知道以前是怎么样的,但是现在第二种的配置应该是有些问题的吧

spring.cloud.nacos.shared.dataids= 应改为 spring.cloud.nacos.config.shared-dataids=

文档写的没问题,只是版本不一样,底层实现不一样,配置的写法就不一样。你现在这个配置spring.cloud.nacos.config.shared-dataids=在 1.2.1 也不推荐使用了,估计现在最终的实现只有第三种。不过我看了两周了,也没看出 shared-configs 和 extension-configs 两个配置的差别,它们底层实现都是基于 com.alibaba.cloud.nacos.NacosConfigProperties.Config 实现。要是用顾名思义这个词来理解的话,它们的区别主要是为了在配置的时候写得比较清晰,容易区分哪个是共享哪个是扩展,不过呢,我试过了拿 extension-configs 来当共享配置用好像也是没有问题的。你们怎么理解当前最新版本 1.2.1 呢?请指教,谢谢

mustangxu commented 2 years ago

所以,sharedDataids和extConfig的区别到底在哪里?