本文已收錄 https://github.com/lkxiaolou/lkxiaolou 歡迎star缰贝。
配置中心
業(yè)務(wù)上的配置戳气,功能開關(guān)邦蜜,服務(wù)治理上對(duì)弱依賴的降級(jí),甚至數(shù)據(jù)庫(kù)的密碼等,都可能用到動(dòng)態(tài)配置中心。
在沒有專門的配置中心組件時(shí)羔飞,我們使用硬編碼、或配置文件檐春、或數(shù)據(jù)庫(kù)逻淌、緩存等方式來(lái)解決問(wèn)題。
硬編碼修改配置時(shí)需要重新編譯打包疟暖,配置文件需要重啟應(yīng)用卡儒,數(shù)據(jù)庫(kù)受限于性能,緩存喪失了及時(shí)性俐巴。
可能都不完美骨望,但能從中總結(jié)出配置中心的需求,相對(duì)來(lái)說(shuō)還是比較明確:
- 能夠存儲(chǔ)欣舵、獲取并監(jiān)聽配置(必須)
- 配置變更時(shí)能及時(shí)推送給監(jiān)聽者(必須)
- 有一個(gè)可視化的查看變更配置的控制臺(tái)(必須)
- 配置變更可灰度執(zhí)行(加分)
- 配置變更可回滾(加分)
目前使用最多的配置中心可能是攜程開源的Apollo擎鸠,還有Spring Cloud Config、阿里開源的Nacos缘圈、百度的Disconf等劣光。
Nacos配置中心
Nacos
是Naming and Configuration Service
的縮寫,從名字上能看出它重點(diǎn)關(guān)注的兩個(gè)領(lǐng)域是Naming
即注冊(cè)中心和Configuration
配置中心准验。
本文講解nacos的配置中心的架構(gòu)設(shè)計(jì)和實(shí)現(xiàn)原理赎线,基于2.0.0
版本(注:2.0.0版本與1.x版本區(qū)別較大)
Nacos調(diào)試環(huán)境搭建
- 先從github上clone代碼(網(wǎng)速比較慢,加上--depth=1參數(shù))
git clone --depth=1 https://github.com/alibaba/nacos.git
- 導(dǎo)入IDE糊饱,看代碼垂寥,調(diào)試更方便
- 啟動(dòng)Server端:運(yùn)行console模塊下的Nacos.main(),這個(gè)類掃描的路徑最廣另锋,能啟動(dòng)所有的模塊
JVM參數(shù)可帶上
-Dnacos.standalone=true -Dnacos.functionMode=config
滞项,指定單機(jī)模式,且只啟動(dòng)config模塊--spring.config.additional-location=nacos/distribution/conf
夭坪,程序參數(shù)指定配置文件目錄正常啟動(dòng)文判,console打印出Ncos控制臺(tái)地址,進(jìn)入Nacos控制臺(tái)室梅,輸入用戶名密碼(默認(rèn)均為nacos)即可登錄
- 使用client進(jìn)行測(cè)試戏仓,example模塊下有configExample可進(jìn)行config的測(cè)試疚宇,為了不動(dòng)源代碼,可copy一份configExample進(jìn)行修改測(cè)試
Nacos配置模型
namespace + group + dataId 唯一確定一個(gè)配置
- namespace:與client綁定赏殃,一個(gè)clinet對(duì)應(yīng)到一個(gè)namespace敷待,可用來(lái)隔離環(huán)境或區(qū)分租戶
- group:分組,區(qū)分業(yè)務(wù)
- dataId:配置的id
客戶端啟動(dòng)流程
- 參數(shù)準(zhǔn)備時(shí)仁热,如果配置了nacos服務(wù)端地址榜揖,則直接使用;如果配置了endpoint抗蠢,則從endpoint中獲取nacos服務(wù)端地址举哟,這樣有個(gè)好處是服務(wù)端地址變更,擴(kuò)縮容都無(wú)需重啟client迅矛,更詳細(xì)可參考
https://nacos.io/en-us/blog/namespace-endpoint-best-practices.html
- 在客戶端第一次與服務(wù)端交互時(shí)創(chuàng)建GRPC連接妨猩,隨機(jī)挑選一臺(tái)server建立連接,后續(xù)都使用該連接秽褒,請(qǐng)求失敗都會(huì)有重試册赛,針對(duì)請(qǐng)求級(jí)別也有限流;重試失敗或者服務(wù)端主動(dòng)斷開連接震嫉,則會(huì)重新挑選一臺(tái)server進(jìn)行建鏈
請(qǐng)求模型
從gRPC的proto文件能看出請(qǐng)求與返回的定義比較統(tǒng)一
message Metadata {
string type = 3;
string clientIp = 8;
map<string, string> headers = 7;
}
message Payload {
Metadata metadata = 2;
google.protobuf.Any body = 3;
}
service Request {
// Sends a commonRequest
rpc request (Payload) returns (Payload) {
}
}
- type是請(qǐng)求/返回類的類名
- clientIp是客戶端ip
- headers是攜帶的header信息
- Playload中的body以json格式編碼
在com.alibaba.nacos.api.config.ConfigService
中可以找到所有配置中心能使用的接口
重點(diǎn)關(guān)注這幾個(gè)接口:
- getConfig:讀取配置
- publishConfig:發(fā)布配置
- publishConfigCas:原子的發(fā)布配置,若有被其他線程變更則發(fā)布失敗牡属,類似java中的CAS
- removeConfig:刪除配置
- addListener:監(jiān)聽配置
- removeListener:移除配置的監(jiān)聽
變更推送
采取推拉結(jié)合的方式票堵,既保證時(shí)效性,又保證數(shù)據(jù)一致性
數(shù)據(jù)存儲(chǔ)
Nacos配置中心的數(shù)據(jù)存儲(chǔ)支持內(nèi)嵌的derby
數(shù)據(jù)庫(kù)逮栅,也支持外部數(shù)據(jù)庫(kù)mysql
悴势,內(nèi)嵌數(shù)據(jù)庫(kù)主要是為了單機(jī)測(cè)試時(shí)使用。
其中上文提及的publishConfigCas
的實(shí)現(xiàn)是利用了數(shù)據(jù)庫(kù)update ${table} set ${xx}=${zz} where md5=${old_md5}
來(lái)實(shí)現(xiàn)措伐,如果已經(jīng)這條數(shù)據(jù)被變更特纤,則這次publish會(huì)失敗。
灰度和回滾
當(dāng)勾選灰度發(fā)布時(shí)可填寫灰度的ip進(jìn)行推送侥加,不在灰度列表內(nèi)的ip則不會(huì)接受到變更推送捧存,并且灰度和正式是區(qū)分開的。
灰度的實(shí)現(xiàn)是記錄下了每次的發(fā)布担败,回滾到指定版本即可昔穴。
結(jié)語(yǔ)
本文從背景出發(fā),結(jié)合Nacos配置中心的各個(gè)重要模塊進(jìn)行了一一解釋提前,能夠從整體上對(duì)Nacos的配置中心有一個(gè)把握吗货。期望后續(xù)能對(duì)Nacos注冊(cè)中心進(jìn)行分析介紹。