https://github.com/go-chassis/go-chassis是一個微服務開發框架,而微服務開發框架帶來的其中一個課題就是:當單體應用向微服務轉型後,有大量的配置須要管理,而你並不但願登陸到遠端機器去更改配置,並重啓應用,尤爲是如今已是容器的時代了,也不但願由於一個配置的變動,而發佈一個新的軟件包。那麼分佈式系統中每一個進程的動態配置管理及運行時熱加載就成爲了一個亟待解決的問題。https://github.com/go-chassis/go-archaius爲go chassis而生,他汲取了netflix的archaius框架經驗,並作出來本身的創新特性。java
Source: 配置源是一種標準接口,能夠經過實現一個source來接入不一樣配置源,它定義配置來自哪一個資源,配置能夠來自配置中心configcenter,來自本地文件,來自環境變量或是啓動命令行。source負責將配置項緩存到本地內存。用戶能夠選擇加載任意的source實現。
git
Config center source: 配置中心源不一樣於其餘source,它包含一個client抽象,能夠對接不一樣的生態系統,目前對接了攜程開源的配置中心Apollo。github
Config manager:負責整合管理全部source的配置,每一個source能夠定義優先級,當經過manager獲取配置時,若是2個不一樣的source有相同的配置,那麼就會取最大優先級的配置。算法
Event Dispatcher:用戶能夠經過Archaius API進行配置變化監聽,當source內部的配置項新增,更新,刪除配置時,都會通知到監聽器。緩存
Source優先級:優先級由大到小依次爲Config center,CLI,ENV,file,當有相同配置項的時候僅優先級大的配置生效。在一個分佈式系統中,遠程的配置中心理應擁有最大優先級,而在本地運行一個獨立的進程時,一般的思惟是,命令行參數優先級高於環境變量,高於本地文件內容。擁有了這樣一套機制後,用戶就無需再寫代碼處理配置項生效邏輯。bash
Config Factory: 封裝了event 和 config manager的API架構
Archaius API: 封裝底層實現,提供友好的API供開發者使用併發
獲取配置有2種不一樣的手段:框架
1. 調用archaius API的Get 方法分佈式
2. 註冊監聽器
事件的觸發是由soruce的開發者來決定的,每一個source的行爲會有不一樣:
命令行與環境變量是不會產生任何事件的,當archaius運行後配置項就已經定下來了,只能使用Get方法獲取。而文件source會在啓動後拉取一遍本地文件內容並轉換爲配置項(可自定義轉換算法,決定配置項形態),以後持續監聽本地文件變化,當有變化發生時會刷新本地配置並通知到監聽器。因此2種方法都支持。config center source行爲與文件又不一樣,在啓動後,它就會週期拉取配置中心的配置,而且對比每一次配置項的不一樣,並觸發不一樣類型事件。
假設程序有一個配置文件叫a.yaml,內容以下
registry:
enabled: true
interval: 30s複製代碼
要考慮該如何去對待這raw data,目前有2種方式
第一種,將配置項拆分爲java properties風格的配置:
registry.refresh: true
registry.interval: 30s
go archaius開放了file handler接口,容許你決定如何將文件內容處理爲配置項
那麼在遠程的配置中心中,key value的管理方式就要遵循 file handler的行爲,當你想變動registry.refresh時,就要在配置中心種更改這個配置項及值。
相似於開關類的配置項,這種java properties的管理方式仍是不錯的,當一個配置項改變時觸發一次事件。
可是有一類配置項並不適合如此管理,這就是第二種方式,好比go chassis中的路由管理配置文件:
一般都須要大範圍的更改配置項,那麼若是還使用切分的方式在配置中心中管理將會引發go archaius運行時大量的事件觸發,而且,用戶在使用體驗上大打折扣,處處去找分散的配置項,逐一更改。正確的行爲是,將文件名做爲配置中心中的key,文件內容做爲value。用戶須要更改時,去找對應的文件名便可,修改後一次性下發,只會觸發一次事件,完成路由的變動。
開發者應根據實際場景判斷如何處理配置項形態。也能夠本身實現handler來決定配置項形態
在運行時能夠隨時經過統一的配置中心或者本地文件(不推薦分佈式環境登到機器裏改文件,但在本地debug時仍是推薦使用文件來測試程序的熱加載邏輯)更改配置了,那麼接下來要解決的問題就是配置在運行時生效。
這裏的技巧是使用go語言中的讀寫鎖。我以go chassis中路由配置來講明
go chassis運行時老是會有不斷地大併發數據訪問router config這塊緩存,使用一個讀寫鎖lock中的讀鎖,每次訪問緩存都用讀鎖,使用後,解開讀鎖。
向archaius註冊監聽器,須要本身編寫監聽器的邏輯,每當事件出發後就會經過archaius中的數據構建一個結構體數據,而後將數據存到本地緩存,首先使用lock的寫鎖鎖住router config,更新後,解開寫鎖。
在這樣的機制下,就能夠作到運行時熱加載配置項而無需重啓服務。
一個本地文件事件監控的例子
https://github.com/go-chassis/go-archaius/tree/master/examples/event
管理本地多文件的例子
https://github.com/go-chassis/go-archaius/tree/master/examples/file
https://juejin.im/post/5ba34495e51d450e9e440d1f