爲了更好的解決分佈式環境下多臺服務實例的配置統一管理問題,本文提出了一套完整的分佈式配置管理解決方案(簡稱爲disconf[4],下同)。首先,實現了同構系統的配置發佈統一化,提供了配置服務server,該服務能夠對配置進行持久化管理並對外提供restful接口,在此基礎上,基於zookeeper實現對配置更改的實時推送,而且,提供了穩定有效的容災方案,以及用戶體驗良好的編程模型和WEB用戶管理界面。其次,實現了異構系統的配置包管理,提出基於zookeeper的全局分佈式一致性鎖來實現主備統一部署、系統異常時的主備自主切換。經過在百度內部以及外部等多個產品線的實踐結果代表,本解決方案是有效且穩定的。mysql
在一個分佈式環境中,同類型的服務每每會部署不少實例。這些實例使用了一些配置,爲了更好地維護這些配置就產生了配置管理服務。經過這個服務能夠輕鬆地管理成千上百個服務實例的配置問題。git
王阿晶提出了基於zooKeeper的配置信息存儲方案的設計與實現[1], 它將全部配置存儲在zookeeper上,這會致使配置的管理不那麼方便,並且他們沒有相關的源碼實現。淘寶的diamond[2]是淘寶內部使用的一個管理持久配置的系統,它具備完整的開源源碼實現,它的特色是簡單、可靠、易用,淘寶內部絕大多數系統的配置都採用diamond來進行統一管理。他將全部配置文件裏的配置打散化進行存儲,只支持KV結構,而且配置更新的推送是非實時的。百度內部的BJF配置中心服務[3]採用了相似淘寶diamond的實現,也是配置打散化、只支持KV和非實時推送。程序員
同構系統是市場的主流,特別地,在業界大量使用部署虛擬化(如JPAAS系統,SAE,BAE)的狀況下,同一個系統使用同一個部署包的情景會愈來愈多。可是,異構系統也有必定的存在乎義,譬如,對於「拉模式」的多個下游實例,同一時間點只能只有一個下游實例在運行。在這種情景下,就存在多臺實例機器有「主備機」模式的問題。目前國內並無很明顯的解決方案來統一解決此問題。github
disconf是一套完整的基於zookeeper的分佈式配置統一解決方案。web
它的功能特色是redis
它的設計理念是:spring
disconf服務集羣模式:sql
disconf的模塊架構圖:數據庫
每一個模塊的簡單介紹以下:編程
運行流程詳細介紹:
與2.0版本的主要區別是支持了:主備分配功能/主備切換事件。
disconf-web提供了先後端分離的web架構,具體可見:https://github.com/knightliao/disconf/tree/master/disconf-web
本部分會重點介紹disconf-client的實現方式。
本實現會涉及到 配置倉庫容器模塊、掃描模塊、下載模塊、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; } }
本實現提供了無任何代碼侵入方式的分佈式配置。
ReloadablePropertiesFactoryBean繼承了Spring Properties文件的PropertiesFactoryBean類,管理全部當配置更新時要進行reload的配置文件。對於被管理的每個配置文件,都會經過 配置倉庫容器模塊、掃描模塊、下載模塊、watch模塊 進行配置獲取至配置倉庫裏。
ReloadingPropertyPlaceholderConfigurer繼承了Spring Bean配置值控制類PropertyPlaceholderConfigurer。在第一次掃描spring bean裏,disconf會記錄配置文件的配置與哪些bean有關聯。
ReloadConfigurationMonitor是一個定時任務,定時check本地配置文件是否有更新。
當配置中心的配置被更新時,配置文件會被下載至實例本地,ReloadConfigurationMonitor即會監控到此行爲,而且通知 ReloadingPropertyPlaceholderConfigurer 對相關的bean類進行值更新。
特別的,此種方式沒法解決併發狀況下配置統一輩子效的問題。
在實現中,爲每一個配置提供主備選擇的概念。用戶實例在獲取配置前須要先進行全局惟一性競爭才能獲得配置值。在這裏,咱們採用基於zookeeper的全局惟一性鎖來實現。
淘寶Diamond[2] | Disconf | 比較 | |
---|---|---|---|
數據持久性 | 存儲在mysql上 | 存儲在mysql上 | 都持久化到數據庫裏,都易於管理 |
推拉模型 | 拉模型,每隔15s拉一次全量數據 | 基於Zookeeper的推模型,實時推送 | disconf基於分佈式的Zookeeper來實時推送,在穩定性、實效性、易用性上均優於diamond |
配置讀寫 | 支持實例對配置讀寫。支持某臺實例寫配置數據,並廣播到其它實例上 | 只支持實例對配置讀。經過在disconf-web上更新配置到達到廣播寫到全部應用實例 | 從目前的應用場景來看,實例對配置的寫需求不是那麼明顯。disconf支持的中心化廣播方案可能會與人性思考更加類似。 |
容災 | 多級容災模式,配置數據會dump在本地,避免中心服務掛機時沒法使用 | 多級容災模式,優先讀取本地配置文件。 | 雙方均支持在中心服務掛機時配置實例仍然可使用 |
配置數據模型 | 只支持KV結構的數據,非配置文件模式 | 支持傳統的配置文件模式(配置文件),亦支持KV結構數據(配置項) | 使用配置文件的編程方式可能與程序員的編程習慣更爲類似,更易於接受和使用。 |
編程模型 | 須要將配置文件拆成多個配置項,沒有明顯的編程模型 | 在使用配置文件的基礎上,提供了註解式和基於XML的兩種編程模型 | 無 |
併發性 | 多條配置要同時生效時,沒法解決併發同時生效的問題 | 基於註解式的配置,能夠解決併發性問題 | 無 |
</table>