dubbo-go 中如何實現遠端配置管理

joke59發表於2020-02-27

之前在 Apache/dubbo-go(以下簡稱 dubbo-go )社群中,有同學希望配置檔案不僅可以放於本地,還可以放於配置管理中心裡。那麼,放在本地和配置管理中心究竟有哪些不一樣呢?

放在本地,每次更新需要重啟,配置檔案管理困難,無法做到實時更新即刻生效。此外,本地檔案還依賴人工版本控制,在微服務的場景下,大大的增加了運維的成本與難度。

而配置管理中心提供了統一的配置檔案管理,支援檔案更新、實時同步、統一版本控制、許可權管理等功能。

目標

基於以上幾個背景,可以總結出以下 目標

  • 與 Dubbo 現有的配置中心內的配置檔案相容,降低新增語言棧的學習成本;
  • 支援多種配置檔案格式;
  • 支援主流配置中心,適應不一樣的使用場景,實現高擴充套件的配置下發;

配置中心

配置中心在 dubbo-go 中主要承擔以下場景的職責:

  • 作為外部化配置中心,即儲存 dubbo.properties 配置檔案,此時,key 值通常為檔名如 dubbo.properties , value 則為配置檔案內容。
  • 儲存單個配置項,如各種開關項、常量值等。
  • 儲存服務治理規則,此時 key 通常按照 “服務名 + 規則型別” 的格式來組織,而 value 則為具體的治理規則。

dubbo-go 應支援 dubbo 中所有支援的各種開源配置中心,包括:

  • Apollo :攜程框架部門研發的分散式配置中心,能夠集中化管理應用不同環境、不同叢集的配置,配置修改後能夠實時推送到應用端,並且具備規範的許可權、流程治理等特性,適用於微服務配置管理場景。
  • zookeeper :一個分散式的,開放原始碼的分散式應用程式協調服務,是 Google 的 Chubby 一個開源的實現,是 Hadoop 和 Hbase 的重要元件。它是一個為分散式應用提供一致性服務的軟體,提供的功能包括:配置維護、域名服務、分散式同步、組服務等。
  • nacos : Alibaba 開源的配置管理元件,提供了一組簡單易用的特性集,幫助您實現動態服務發現、服務配置管理、服務及流量管理。

而考慮到某些公司內部有自身的研發的配置中心,又或者當前流行而 Dubbo 尚未支援的配置中心,如 etcd,我們的核心在於設計一套機制,允許我們,也包括使用者,可以通過擴充套件介面新的實現,來快速接入不同的配置中心。

那在 dubbo-go 中究竟怎麼實現呢?我們的答案是:基於動態的外掛機制在啟動時按需載入配置中心的不同實現。

實現該部分功能放置於一個獨立的子專案中,見:https://github.com/apache/dubbo-go/tree/master/config_center

dubbo-go 設計

原邏輯為:啟動時讀取本地配置檔案,將其載入進記憶體,通過配置檔案中的配置讀取註冊中心的資訊獲取服務提供者,註冊服務消費者。

有些讀者會有點困惑,不是說好了使用配置中心的,為什麼現在又要讀取本地配置呢?答案就是,讀取的這部分資訊分成兩部分:

  • 使用什麼作為配置中心;

  • 該配置中心的後設資料,比如說使用 zookeeper 作為配置中心,那麼 zookeeper 的連結資訊就是後設資料,畢竟我們只有在知道了連結資訊之後才能連上 zookeeper;

在改造的時候,需要考慮以下的問題:

  1. 如何實現支援多個配置中心?如何實現按需載入?

通過抽象 DynamicConfiguration 讓開發者可以快速支援多個配置中心。

使用者匯入指定的元件包後,在啟動階段將需要的元件載入進記憶體中,以便給程式按需呼叫,如下圖綠色部分。

  1. 配置中心的配置載入階段在什麼時候?

應在讀取配置檔案階段後,讀取並解析本地配置檔案中配置中心資訊。初始化配置中心連結,讀取 /dubbo/config/dubbo/dubbo.properties 與 /dubbo/config/dubbo/應用名/dubbo.properties ,並將其載入到記憶體之中覆蓋原有配置,監聽其變更,實時更新至記憶體,如下圖藍色部分。

ConfigCenterFactory

使用者載入對應配置中心模組後,在初始化階段加入各配置中心模組往其中註冊其初始化類。

DynamicConfigurationFactory

整個動態配置中心的關鍵點就在 DynamicConfigurationFactory 上,其中通過解析內部自定義的 URL ,獲取其協議型別,反射其引數,用於建立配置中心的連結。

如:

配置檔案中配置

config_center:
  protocol: zookeeper
  address: 127.0.0.1:2181
  namespace: test

dubbo-go 內部會解析為

zookeeper://127.0.0.1:2181?namespace=test

在內部傳遞,用於初始化配置中心連結。

PS:在 dubbo-go 中到處可見這種內部協議,透徹理解這個內部協議對閱讀 dubbo-go 程式碼很有幫助。

DynamicConfiguration

該介面規定了各個配置中心需要實現的功能:

  • 配置資料反序列化方式:目前只有 properties 反序列化,參見: DefaultConfigurationParser 。
  • 增加監聽器:用於增加監聽資料變化後增加特定邏輯(受限於配置中心 client 端實現)。
  • 刪除監聽器:刪除已有監聽器(受限於配置中心 client 端實現,目前所知 nacos client 沒有提供該方法)。
  • 獲取路由配置:獲取路由表配置。
  • 獲取應用級配置:獲取應用層級配置,如:協議型別配置等。

實現

優先考慮與現有 dubbo 設計相容,從而降低使用者的學習成本,dubbo-admin 作為服務提供者實現應用級配置管理, dubbo-go 作為消費端實現配置下發管理功能。以 zookeeper 為例,對服務提供者與服務消費者進行整體流程分析。

如何儲存配置管理

dubbo-admin 配置管理中增加 global 配置,zookeeper 中會自動生成其對應配置節點,內容均為 dubbo-admin 中設定的配置。

  • /dubbo/config/dubbo/dubbo.properties 對應全域性配置檔案。
  • /dubbo/config/dubbo/ 應用名 /dubbo.properties 對應指定應用配置檔案。

節點路徑

上圖展示了 dubbo.properties 檔案在 zookeeper 和 Apollo 中的儲存結構:

zookeeper

  • 名稱空間 namespace 都為: dubbo

  • 分組 group :全域性級別為 dubbo , 所有應用共享;應用級別為應用名 demo-provider ,只對該應用生效

  • key : dubbo.properties

Apollo

  • app_id : 自由指定,預設: dubbo ,最好與 zookeeper namespace 一致

  • cluster : 自由指定,最好與 zookeeper group 一致

  • 名稱空間 namespace : dubbo.properties

zookeeper 與 Apollo 最大的不一樣就在於 dubbo.properties 所在的節點。

實現配置管理中心支援

以 Apollo 為例,簡單的介紹,如何實現支援一個新的配置管理中心。

選擇配置管理中心 Client / SDK

本例中使用的 Apollo Go Client 為:https://github.com/zouyx/agollo

PS: 如沒找到,自己實現也是可以的哦。

節點路徑

因為每個配置管理中心的儲存結構各有特點,導致 dubbo 在使用外部配置管理中心時,儲存配置節點的結構不一樣。在 dubbo-configcenter 找到希望支援的配置管理中心,而本例中 Apollo 則在 ApolloDynamicConfiguration.java

註釋中表明,Apollo namespace = governance (governance .properties) 用於治理規則,namespace = dubbo (dubbo.properties) 用於配置檔案。

實現 DynamicConfiguration

新建建立客戶端方法,最好客戶端保持為單例。

以下為必須實現的方法,以下方法用於獲取配置中心配置。

  • GetInternalProperty:在配置檔案(Apollo 為 namespace)中,根據 key 獲取對應 value;
  • GetRule:獲取治理配置檔案(Apollo 為 namespace);
  • GetProperties:獲取整個配置檔案(Apollo 為 namespace);

可選擇實現的方法,如不實現,則不能動態更新 dubbo-go 中配置資訊。

  • RemoveListener
  • AddListener

而 Parser & SetParser 使用預設實現即可,預設為 Properties 轉換器。

更多資訊,參考:dubbo-go-apollo

使用方法

從上面的設計裡面,也能大概猜到怎麼使用了:

很顯然,使用配置中心並不複雜,只需要把對應的依賴引入進來。在包初始化的時候,會建立出來對應的配置中心的實現。比如說載入 ZooKeeper 或者 Apollo 作為配置中心:

zookeeper

_ "github.com/apache/dubbo-go/config_center/zookeeper"

Apollo

_ "github.com/apache/dubbo-go/config_center/apollo"

當然僅僅載入還不夠,比如說雖然我載入了 zookeeper,但是我還需要知道怎麼連上這個配置中心,即前面提到的配置中心的後設資料,這部分資訊是需要在本地配置出來的。比如說:

zookeeper

config_center:
  protocol: "zookeeper"
  address: "127.0.0.1:2181"

Apollo

如果需要使用 Apollo 作為配置中心,請提前建立 namespace : dubbo.properties ,用於配置管理。

config_center:
  protocol: "apollo"
  address: "127.0.0.1:8070"
  app_id: test_app
  cluster: dev

總結

更加具體的實現,我就不詳細論述,大家可以去看原始碼,歡迎大家持續關注,或者貢獻程式碼。

整個配置中心的功能,麻雀雖小,但五臟俱全。目前並不算是十分完善,但是整個框架層面上來說,是走在了正確的路上。從擴充套件性來說,是比較便利。目前支援的配置中心還不夠豐富,只有 zookeeper 與 Apollo ,支援的配置檔案格式也只有 properties ,雖然能滿足基本使用場景,距離完善還有還長遠的路。

未來計劃:

  1. nacos(已有 PR , 正在 review )
  2. etcd(未支援)
  3. consul(未支援)
  4. 豐富的檔案配置格式,如: yml , xml 等

作者資訊

鄒毅賢,Github ID @zouyx,開源愛好者,就職於 SheIn 供應鏈部門,負責供應鏈開放平臺。

更多原創文章乾貨分享,請關注公眾號
  • dubbo-go 中如何實現遠端配置管理
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章