天天看點

Go語言微服務開發架構:Go chassis

摘要:分布式系統中每個程序的動态配置管理及運作時熱加載就成為了一個亟待解決的問題。go chassis汲取了netflix的archaius架構經驗,并做出來自己的創新特性。

引言

https://github.com/go-chassis/go-chassis是一個微服務開發架構,而微服務開發架構帶來的其中一個課題就是:當單體應用向微服務轉型後,有大量的配置需要管理,而你并不希望登入到遠端機器去更改配置,并重新開機應用,尤其是現在已經是容器的時代了,也不希望因為一個配置的變更,而釋出一個新的軟體包。那麼分布式系統中每個程序的動态配置管理及運作時熱加載就成為了一個亟待解決的問題。https://github.com/go-chassis/go-archaius為go chassis而生,他汲取了netflix的archaius架構經驗,并做出來自己的創新特性。

架構

Go語言微服務開發架構:Go chassis

Source: 配置源是一種标準接口,可以通過實作一個source來接入不同配置源,它定義配置來自哪個資源,配置可以來自配置中心configcenter,來自本地檔案,來自環境變量或是啟動指令行。source負責将配置項緩存到本地記憶體。使用者可以選擇加載任意的source實作。

Config center source: 配置中心源不同于其他source,它包含一個client抽象,可以對接不同的生态系統,目前對接了攜程開源的配置中心Apollo。

Config manager:負責整合管理所有source的配置,每個source可以定義優先級,當通過manager擷取配置時,如果2個不同的source有相同的配置,那麼就會取最大優先級的配置。

Event Dispatcher:使用者可以通過Archaius API進行配置變化監聽,當source内部的配置項新增,更新,删除配置時,都會通知到監聽器。

Source優先級:優先級由大到小依次為Config center,CLI,ENV,file,當有相同配置項的時候僅優先級大的配置生效。在一個分布式系統中,遠端的配置中心理應擁有最大優先級,而在本地運作一個獨立的程序時,通常的思維是,指令行參數優先級高于環境變量,高于本地檔案内容。擁有了這樣一套機制後,使用者就無需再寫代碼處理配置項生效邏輯。

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接口,允許你決定如何将檔案内容處理為配置項

Go語言微服務開發架構:Go chassis

那麼在遠端的配置中心中,key value的管理方式就要遵循 file handler的行為,當你想變更registry.refresh時,就要在配置中心種更改這個配置項及值。

類似于開關類的配置項,這種java properties的管理方式還是不錯的,當一個配置項改變時觸發一次事件。

但是有一類配置項并不适合如此管理,這就是第二種方式,比如go chassis中的路由管理配置檔案:

Go語言微服務開發架構:Go chassis

通常都需要大範圍的更改配置項,那麼如果還使用切分的方式在配置中心中管理将會引起go archaius運作時大量的事件觸發,并且,使用者在使用體驗上大打折扣,到處去找分散的配置項,逐一更改。正确的行為是,将檔案名作為配置中心中的key,檔案内容作為value。使用者需要更改時,去找對應的檔案名即可,修改後一次性下發,隻會觸發一次事件,完成路由的變更。

開發者應根據實際場景判斷如何處理配置項形态。也可以自己實作handler來決定配置項形态

配置運作時熱加載

在運作時可以随時通過統一的配置中心或者本地檔案(不推薦分布式環境登到機器裡改檔案,但在本地debug時還是推薦使用檔案來測試程式的熱加載邏輯)更改配置了,那麼接下來要解決的問題就是配置在運作時生效。

這裡的技巧是使用go語言中的讀寫鎖。我以go chassis中路由配置來說明

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

Go chassis介紹

https://juejin.im/post/6844903682362834952

本文分享自華為雲社群《Go語言分布式系統配置管理實踐--go archaius》,原文作者:APTX-486977 。

點選關注,第一時間了解華為雲新鮮技術~

繼續閱讀