首頁 > 軟體

Disconf實現分散式設定管理的原理與設計

2022-03-08 16:01:43

技術背景

在一個分散式環境中,同型別的服務往往會部署很多範例。這些範例使用了一些設定,為了更好地維護這些設定就產生了設定管理服務。通過這個服務可以輕鬆地管理成千上百個服務範例的設定問題。

王阿晶提出了基於zooKeeper的設定資訊儲存方案的設計與實現[1], 它將所有設定儲存在zookeeper上,這會導致設定的管理不那麼方便,而且他們沒有相關的原始碼實現。淘寶的diamond[2]是淘寶內部使用的一個管理持久設定的系統,它具有完整的開源原始碼實現,它的特點是簡單、可靠、易用,淘寶內部絕大多數系統的設定都採用diamond來進行統一管理。他將所有組態檔裡的設定打散化進行儲存,只支援KV結構,並且設定更新的推播是非實時的。百度內部的BJF設定中心服務[3]採用了類似淘寶diamond的實現,也是設定打散化、只支援KV和非實時推播。

同構系統是市場的主流,特別地,在業界大量使用部署虛擬化(如JPAAS系統,SAE,BAE)的情況下,同一個系統使用同一個部署包的情景會越來越多。但是,異構系統也有一定的存在意義,譬如,對於“拉模式”的多個下游範例,同一時間點只能只有一個下游範例在執行。在這種情景下,就存在多臺範例機器有“主備機”模式的問題。目前國內並沒有很明顯的解決方案來統一解決此問題。

功能特點與設計理念

disconf是一套完整的基於zookeeper的分散式設定統一解決方案。

功能特點

支援設定(設定項+組態檔)的分散式化管理

  • 設定釋出統一化
  • 設定釋出、更新統一化(雲端儲存、釋出):設定儲存在雲端系統,使用者統一在平臺上進行釋出、更新設定。
  • 設定更新自動化:使用者在平臺更新設定,使用該設定的系統會自動發現該情況,並應用新設定。特殊地,如果使用者為此設定定義了回撥函數類,則此函數類會被自動呼叫。

設定異構系統管理

  • 異構包部署統一化:這裡的異構系統是指一個系統部署多個範例時,由於設定不同,從而需要多個部署包(jar或war)的情況(下同)。使用Disconf後,異構系統的部署只需要一個部署包,不同範例的設定會自動分配。特別地,在業界大量使用部署虛擬化(如JPAAS系統,SAE,BAE)的情況下,同一個系統使用同一個部署包的情景會越來越多,Disconf可以很自然地與他天然契合。 異構主備自動切換:如果一個異構系統存在主備機,主機發生掛機時,備機可以自動獲取主機設定從而變成主機。
  • 異構主備機Context共用工具:異構系統下,主備機切換時可能需要共用Context。可以使用Context共用工具來共用主備的Context。

註解式程式設計,極簡的使用方式:我們追求的是極簡的、使用者程式設計體驗良好的程式設計方式。通過簡單的標註+極簡單的程式碼撰寫,即可完成複雜的設定分散式化。

需要Spring程式設計環境

設計理念

簡單,使用者體驗良好:

  • 摒棄了打散化設定的管理方式[2,3],仍舊採用基於組態檔的程式設計方式,這和程式設計師以前的程式設計習慣(設定都是放在組態檔裡)一致。特別的,為了支援較為小眾的打散化設定功能,還特別支援了設定項。
  • 採用了基於XML無程式碼侵入程式設計方式:只需要幾行XML設定,即可實現組態檔釋出更新統一化、自動化。
  • 採用了基於註解式的弱程式碼侵入程式設計方式:通過程式設計規範,一個組態檔一個設定類,程式碼結構簡單易懂。XML幾乎沒有任何更改,與原springXML設定一樣。真正程式設計時,幾乎感覺不到設定已經分散式化

可以託管任何型別的組態檔,這與[2,3]只能支援KV結構的功能有較大的改進。

設定更新實時推播

提供介面良好Web管理功能,可以非常方便的檢視設定被哪些範例使用了。

詳細設計

架構設計

disconf服務叢集模式:

disconf的模組架構圖:

每個模組的簡單介紹如下:

  • Disconf-core
    • 分散式通知模組:支援設定更新的實時化通知
    • 路徑管理模組:統一管理內部設定路徑URL
  • Disconf-client
    • 設定倉庫容器模組:統一管理使用者範例中本地組態檔和設定項的記憶體資料儲存
    • 設定reload模組:監控本地組態檔的變動,並自動reload到指定bean
    • 掃描模組:支援掃描所有disconf註解的類和域
    • 下載模組:restful風格的下載組態檔和設定項
    • watch模組:監控遠端組態檔和設定項的變化
    • 主備分配模組:主備競爭結束後,統一管理主備分配與主備監控控制
    • 主備競爭模組:支援分散式環境下的主備競爭
  • Disconf-web
    • 設定儲存模組:管理所有設定的儲存和讀取
    • 設定管理模組:支援設定的上傳、下載、更新
    • 通知模組:當設定更新後,實時通知使用這些設定的所有範例
    • 設定自檢監控模組:自動定時校驗範例本地設定與中心設定是否一致
    • 許可權控制:web的簡單許可權控制
  • Disconf-tools
    • context共用模組:提供多範例間context的共用。

流程設計

執行流程詳細介紹:

與2.0版本的主要區別是支援了:主備分配功能/主備切換事件。

  • 啟動事件A:以下按順序發生。
    • A3:掃描靜態註解類資料,並注入到設定倉庫裡。
    • A4+A2:根據倉庫裡的組態檔、設定項,去 disconf-web 平臺裡下載設定資料。這裡會有主備競爭
    • A5:將下載得到的設定資料值注入到倉庫裡。
    • A6:根據倉庫裡的組態檔、設定項,去ZK上監控結點。
    • A7+A2:根據XML設定定義,到 disconf-web 平臺裡下載組態檔,放在倉庫裡,並監控ZK結點。這裡會有主備競爭。
    • A8:A1-A6均是處理靜態類資料。A7是處理動態類資料,包括:範例化設定的回撥函數類;將設定的值注入到設定實體裡。
  • 更新設定事件B:以下按順序發生。
    • B1:管理員在 Disconf-web 平臺上更新設定。
    • B2:Disconf-web 平臺傳送設定更新訊息給ZK指定的結點。
    • B3:ZK通知 Disconf-cient 模組。
    • B4:與A4一樣。
    • B5:與A5一樣。
    • B6:基本與A4一樣,唯一的區別是,這裡還會將設定的新值注入到設定實體裡。
  • 主備機切換事件C:以下按順序發生。
    • C1:發生主機掛機事件。
    • C2:ZK通知所有被影響到的備機。
    • C4:與A2一樣。
    • C5:與A4一樣。
    • C6:與A5一樣。
    • C7:與A6一樣。

模組實現

disconf-web提供了前後端分離的web架構,具體可見:https://github.com/knightliao/disconf/tree/master/disconf-web

本部分會重點介紹disconf-client的實現方式。

註解式disconf實現

本實現會涉及到 設定倉庫容器模組、掃描模組、下載模組、watch模組,

使用AOP攔截的一個好處是可以比較輕鬆的實現設定控制,比如並行環境下的設定統一生效。

特別地,本方式提供的程式設計模式非常簡單,例如使用以下設定類的程式在使用它時,可以直接@Autowired進來進行呼叫,使用它時就和平常使用普通的JavaBean一樣,但其實它已經分散式化了。設定更新時,設定類亦會自動更新。

@Service
@DisconfFile(filename = "redis.properties")
public class JedisConfig {
    // 代表連線地址
    private String host;
    // 代表連線port
    private int port;
    /**
     * 地址, 分散式檔案設定
     * 
     * @return
     */
    @DisconfFileItem(name = "redis.host", associateField = "host")
    public String getHost() {
        return host;
    }
    public void setHost(String host) {
        this.host = host;
    }
    /**
     * 埠, 分散式檔案設定
     * 
     * @return
     */
    @DisconfFileItem(name = "redis.port", associateField = "port")
    public int getPort() {
        return port;
    }
    public void setPort(int port) {
        this.port = port;
    }
}

基於XML設定disconf實現

本實現提供了無任何程式碼侵入方式的分散式設定。

ReloadablePropertiesFactoryBean繼承了Spring Properties檔案的PropertiesFactoryBean類,管理所有當設定更新時要進行reload的組態檔。對於被管理的每一個組態檔,都會通過 設定倉庫容器模組、掃描模組、下載模組、watch模組 進行設定獲取至設定倉庫裡。

ReloadingPropertyPlaceholderConfigurer繼承了Spring Bean設定值控制類PropertyPlaceholderConfigurer。在第一次掃描spring bean 時,disconf會記錄組態檔的設定與哪些bean有關聯。

ReloadConfigurationMonitor是一個定時任務,定時check本地組態檔是否有更新。

當設定中心的設定被更新時,組態檔會被下載至範例本地,ReloadConfigurationMonitor即會監控到此行為,並且通知 ReloadingPropertyPlaceholderConfigurer 對相關的bean類進行值更新。

特別的,此種方式無法解決並行情況下設定統一生效的問題。

主備分配實現

在實現中,為每個設定提供主備選擇的概念。使用者範例在獲取設定前需要先進行全域性唯一性競爭才能得到設定值。在這裡,我們採用基於zookeeper的全域性唯一性鎖來實現。

COMPARISONS

 淘寶Diamond[2]Disconf比較
資料永續性儲存在mysql上儲存在mysql上都持久化到資料庫裡,都易於管理
推拉模型拉模型,每隔15s拉一次全量資料基於Zookeeper的推模型,實時推播disconf基於分散式的Zookeeper來實時推播,不斷是在穩定性、實效性、易用性上均優於diamond
設定讀寫支援範例對設定讀寫。支援某臺範例寫設定資料,並廣播到其它範例上只支援範例對設定讀。通過在disconf-web上更新設定到達到廣播寫到所有應用範例從目前的應用場景來看,範例對設定的寫需求不是那麼明顯。disconf支援的中心化廣播方案可能會與人性思考更加相似。
容災多級容災模式,設定資料會dump在本地,避免中心服務掛機時無法使用多級容災模式,優先讀取本地組態檔。雙方均支援在中心服務掛機時設定範例仍然可以使用
設定資料模型只支援KV結構的資料,非組態檔模式支援傳統的組態檔模式(組態檔),亦支援KV結構資料(設定項)使用組態檔的程式設計方式可能與程式設計師的程式設計習慣更為相似,更易於接受和使用。
程式設計模型需要將組態檔拆成多個設定項,沒有明顯的程式設計模型在使用組態檔的基礎上,提供了註解式和基於XML的兩種程式設計模型
並行性多條設定要同時生效時,無法解決並行同時生效的問題基於註解式的設定,可以解決並行性問題

以上就是Disconf實現分散式設定管理的原理與設計的詳細內容,更多關於Disconf分散式設定管理的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com