Apollo核心概念之“Namespace”

转载于https://github.com/ctripcorp/apollo,by Ctrip, Inc.java

Apollo核心概念之“Namespace”

1. 什么是Namespace?

Namespace是配置项的集合,相似于一个配置文件的概念。git

2. 什么是“application”的Namespace?

Apollo在建立项目的时候,都会默认建立一个“application”的Namespace。顾名思义,“application”是给应用自身使用的,熟悉Spring Boot的同窗都知道,Spring Boot项目都有一个默认配置文件application.yml。在这里application.yml就等同于“application”的Namespace。对于90%的应用来讲,“application”的Namespace已经知足平常配置使用场景了。github

客户端获取“application” Namespace的代码以下:

  Config config = ConfigService.getAppConfig();

客户端获取非“application” Namespace的代码以下:

  Config config = ConfigService.getConfig(namespaceName);

3. Namespace的格式有哪些?

配置文件有多种格式,例如:properties、xml、yml、yaml、json等。一样Namespace也具备这些格式。在Portal UI中能够看到“application”的Namespace上有一个“properties”标签,代表“application”是properties格式的。json

注:非properties格式的namespace,在客户端使用时须要调用ConfigService.getConfigFile(String namespace, ConfigFileFormat configFileFormat)来获取,若是使用Http接口直接调用时,对应的namespace参数须要传入namespace的名字加上后缀名,如datasources.json。markdown

4. Namespace的获取权限分类

Namespace的获取权限分为两种:app

  • private (私有的)
  • public (公共的)

这里的获取权限是相对于Apollo客户端来讲的。框架

4.1 private权限

private权限的Namespace,只能被所属的应用获取到。一个应用尝试获取其它应用private的Namespace,Apollo会报“404”异常。flex

4.2 public权限

public权限的Namespace,能被任何应用获取。spa

5. Namespace的类型

Namespace类型有三种:3d

  • 私有类型
  • 公共类型
  • 关联类型(继承类型)

5.1 私有类型

私有类型的Namespace具备private权限。例如上文提到的“application” Namespace就是私有类型。

5.2 公共类型

5.2.1 含义

公共类型的Namespace具备public权限。公共类型的Namespace至关于游离于应用以外的配置,且经过Namespace的名称去标识公共Namespace,因此公共的Namespace的名称必须全局惟一。

5.2.2 使用场景
  • 部门级别共享的配置
  • 小组级别共享的配置
  • 几个项目之间共享的配置
  • 中间件客户端的配置

5.3 关联类型

5.3.1 含义

关联类型又可称为继承类型,关联类型具备private权限。关联类型的Namespace继承于公共类型的Namespace,用于覆盖公共Namespace的某些配置。例如公共的Namespace有两个配置项

k1 = v1
k2 = v2

  

而后应用A有一个关联类型的Namespace关联了此公共Namespace,且覆盖了配置项k1,新值为v3。那么在应用A实际运行时,获取到的公共Namespace的配置为:

k1 = v3
k2 = v2
5.3.2 使用场景

举一个实际使用的场景。假设RPC框架的配置(如:timeout)有如下要求:

  • 提供一份全公司默认的配置且可动态调整
  • RPC客户端项目能够自定义某些配置项且可动态调整
  1. 若是把以上两点要求去掉“动态调整”,那么作法很简单。在rpc-client.jar包里有一份配置文件,每次修改配置文件而后从新发一个版本的jar包便可。同理,客户端项目修改配置也是如此。
  2. 若是只支持客户端项目可动态调整配置。客户端项目能够在Apollo “application” Namespace上配置一些配置项。在初始化service的时候,从Apollo上读取配置便可。这样作的坏处就是,每一个项目都要自定义一些key,不统一。
  3. 那么如何完美支持以上需求呢?答案就是结合使用Apollo的公共类型的Namespace和关联类型的Namespace。RPC团队在Apollo上维护一个叫“rpc-client”的公共Namespace,在“rpc-client” Namespace上配置默认的参数值。rpc-client.jar里的代码读取“rpc-client”Namespace的配置便可。若是须要调整默认的配置,只须要修改公共类型“rpc-client” Namespace的配置。若是客户端项目想要自定义或动态修改某些配置项,只须要在Apollo 本身项目下关联“rpc-client”,就能建立关联类型“rpc-client”的Namespace。而后在关联类型“rpc-client”的Namespace下修改配置项便可。这里有一点须要指出的,那就是rpc-client.jar是在应用容器里运行的,因此rpc-client获取到的“rpc-client” Namespace的配置是应用的关联类型的Namespace加上公共类型的Namespace。

5.4 例子

以下图所示,有三个应用:应用A、应用B、应用C。

  • 应用A有两个私有类型的Namespace:application和NS-Private,以及一个关联类型的Namespace:NS-Public。
  • 应用B有一个私有类型的Namespace:application,以及一个公共类型的Namespace:NS-Public。
  • 应用C只有一个私有类型的Namespace:application

Namespace例子

5.4.1 应用A获取Apollo配置
 //application 
  Config appConfig = ConfigService.getAppConfig();
  appConfig.getProperty("k1", null); // k1 = v11
  appConfig.getProperty("k2", null); // k2 = v21
  
  //NS-Private
  Config privateConfig = ConfigService.getConfig("NS-Private");
  privateConfig.getProperty("k1", null); // k1 = v3
  privateConfig.getProperty("k3", null); // k3 = v4
  
  //NS-Public,覆盖公共类型配置的状况,k4被覆盖
  Config publicConfig = ConfigService.getConfig("NS-Public");
  publicConfig.getProperty("k4", null); // k4 = v6 cover
  publicConfig.getProperty("k6", null); // k6 = v6
  publicConfig.getProperty("k7", null); // k7 = v7

 

5.4.2 应用B获取Apollo配置
//application
  Config appConfig = ConfigService.getAppConfig();
  appConfig.getProperty("k1", null); // k1 = v12
  appConfig.getProperty("k2", null); // k2 = null
  appConfig.getProperty("k3", null); // k3 = v32
  
  //NS-Private,因为没有NS-Private Namespace 因此获取到default value
  Config privateConfig = ConfigService.getConfig("NS-Private");
  privateConfig.getProperty("k1", "default value"); 
  
  //NS-Public
  Config publicConfig = ConfigService.getConfig("NS-Public");
  publicConfig.getProperty("k4", null); // k4 = v5
  publicConfig.getProperty("k6", null); // k6 = v6
  publicConfig.getProperty("k7", null); // k7 = v7

 

5.4.3 应用C获取Apollo配置
//application
  Config appConfig = ConfigService.getAppConfig();
  appConfig.getProperty("k1", null); // k1 = v12
  appConfig.getProperty("k2", null); // k2 = null
  appConfig.getProperty("k3", null); // k3 = v33
  
  //NS-Private,因为没有NS-Private Namespace 因此获取到default value
  Config privateConfig = ConfigService.getConfig("NS-Private");
  privateConfig.getProperty("k1", "default value"); 
  
  //NS-Public,公共类型的Namespace,任何项目均可以获取到
  Config publicConfig = ConfigService.getConfig("NS-Public");
  publicConfig.getProperty("k4", null); // k4 = v5
  publicConfig.getProperty("k6", null); // k6 = v6
  publicConfig.getProperty("k7", null); // k7 = v7

 

5.4.4 ChangeListener

以上代码例子中能够看到,在客户端Namespace映射成一个Config对象。Namespace配置变动的监听器是注册在Config对象上。

因此在应用A中监听application的Namespace代码以下:

Config appConfig = ConfigService.getAppConfig();
appConfig.addChangeListener(new ConfigChangeListener() {
  public void onChange(ConfigChangeEvent changeEvent) {
    //do something
  }
})

 

在应用A中监听NS-Private的Namespace代码以下:

Config privateConfig = ConfigService.getConfig("NS-Private");
privateConfig.addChangeListener(new ConfigChangeListener() {
  public void onChange(ConfigChangeEvent changeEvent) {
    //do something
  }
})

 

在应用A、应用B、应用C中监听NS-Public的Namespace代码以下:

Config publicConfig = ConfigService.getConfig("NS-Public");
publicConfig.addChangeListener(new ConfigChangeListener() {
  public void onChange(ConfigChangeEvent changeEvent) {
    //do something
  }
})
相关文章
相关标签/搜索