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
  }
})
相關文章
相關標籤/搜索