作者 | 宋順
編輯 | 小智
隨著微服務(wù)的流行睬愤,應(yīng)用和機(jī)器數(shù)量急劇增長(zhǎng),程序配置也愈加繁雜:各種功能的開(kāi)關(guān)稳懒、參數(shù)的配置舌菜、服務(wù)器的地址等等。在這樣的大環(huán)境下澈蚌,傳統(tǒng)的通過(guò)配置文件摹芙、數(shù)據(jù)庫(kù)等方式已經(jīng)越來(lái)越無(wú)法滿足我們對(duì)配置管理的需求。配置中心宛瞄,應(yīng)運(yùn)而生浮禾!在一定程度上交胚,配置中心就成為了微服務(wù)的大腦,如何用好這個(gè)大腦盈电,讓微服務(wù)更智能蝴簇?本文整理自攜程框架架構(gòu)研發(fā)部技術(shù)專家宋順在 QCon 上海 2018 站的演講。
背景介紹
隨著微服務(wù)的流行匆帚,應(yīng)用和機(jī)器數(shù)量急劇增長(zhǎng)熬词,程序配置也愈加繁雜:各種功能的開(kāi)關(guān)、參數(shù)的配置吸重、服務(wù)器的地址等等互拾。同時(shí),我們對(duì)程序配置的期望值也越來(lái)越高:配置修改后實(shí)時(shí)生效嚎幸,灰度發(fā)布颜矿,分環(huán)境、分集群管理嫉晶,完善的權(quán)限骑疆、審核機(jī)制等等。
在這樣的大環(huán)境下替废,傳統(tǒng)的通過(guò)配置文件箍铭、數(shù)據(jù)庫(kù)等方式已經(jīng)越來(lái)越無(wú)法滿足我們對(duì)配置管理的需求。
配置中心舶担,應(yīng)運(yùn)而生!
通過(guò)配置中心彬呻,我們可以方便地管理微服務(wù)在不同環(huán)境中的配置衣陶,從而可以在運(yùn)行時(shí)動(dòng)態(tài)調(diào)整服務(wù)行為,真正實(shí)現(xiàn)配置即『控制』的目標(biāo)闸氮。所以剪况,在一定程度上,配置中心就成為了微服務(wù)的大腦蒲跨,如何用好這個(gè)大腦译断,讓微服務(wù)更『智能』,也就成為了一項(xiàng)比較重要的議題或悲。
為什么需要配置中心孙咪?
程序的發(fā)布其實(shí)和衛(wèi)星的發(fā)射有一些相似之處。
當(dāng)衛(wèi)星發(fā)射升天后巡语,基本就處于自主駕駛狀態(tài)了翎蹈,一般情況下就是按照預(yù)設(shè)的軌道運(yùn)行,間歇可能會(huì)收到一些來(lái)自地面的『控制』信號(hào)對(duì)運(yùn)行姿態(tài)進(jìn)行一定的調(diào)整男公。
程序發(fā)布其實(shí)也是這樣荤堪,當(dāng)程序發(fā)布到生產(chǎn)環(huán)境后,一般就是按照預(yù)設(shè)的邏輯運(yùn)行,我們無(wú)法直接去干預(yù)程序的行為澄阳,不過(guò)可以通過(guò)調(diào)整配置參數(shù)來(lái)動(dòng)態(tài)調(diào)整程序的行為拥知。這些配置參數(shù)就代表著我們對(duì)程序的『控制』信號(hào)。
由此可見(jiàn)碎赢,配置對(duì)程序的運(yùn)行非常重要低剔,我們需要一種可靠性高、實(shí)時(shí)性好的手段揩抡,從而可以隨時(shí)對(duì)程序『發(fā)號(hào)施令』户侥。
鑒于配置對(duì)程序正確運(yùn)行的重要性,所以配置的治理就顯得尤為重要了峦嗤,比如:
1蕊唐、權(quán)限控制、審計(jì)日志
由于配置能改變程序的行為烁设,不正確的配置甚至能引起災(zāi)難替梨,所以對(duì)配置的修改必須有比較完善的權(quán)限控制。同時(shí)也需要有一套完善的審計(jì)機(jī)制装黑,能夠方便地追溯是誰(shuí)改的配置副瀑、改了什么、什么時(shí)候改的等等恋谭。
2糠睡、灰度發(fā)布、配置回滾
對(duì)于一些比較重要的配置變更疚颊,我們一般會(huì)傾向于先在少量機(jī)器上修改看看效果狈孔,如果沒(méi)問(wèn)題再推給所有機(jī)器。同時(shí)如果發(fā)現(xiàn)配置改得有問(wèn)題的話材义,需要能夠方便地回滾配置均抽。
3、不同環(huán)境其掂、集群管理
同一份程序在不同的環(huán)境(開(kāi)發(fā)油挥,測(cè)試,生產(chǎn))款熬、不同的集群(如不同的數(shù)據(jù)中心)經(jīng)常需要有不同的配置深寥,所以需要有完善的環(huán)境、集群配置管理贤牛。
單體應(yīng)用時(shí)代翩迈,應(yīng)用數(shù)量比較少,配置也相對(duì)比較簡(jiǎn)單盔夜,還有可能讓運(yùn)維登上機(jī)器一臺(tái)一臺(tái)修改程序的配置文件负饲。
隨著微服務(wù)的流行堤魁,大應(yīng)用拆成小應(yīng)用,小應(yīng)用拆成多個(gè)獨(dú)立的服務(wù)返十,導(dǎo)致微服務(wù)的節(jié)點(diǎn)數(shù)量非常多妥泉,配置也隨著服務(wù)數(shù)量增加而急劇增長(zhǎng),再讓運(yùn)維登上機(jī)器一臺(tái)一臺(tái)手工修改配置不僅效率低洞坑,而且還容易出錯(cuò)盲链。如果碰到了緊急事件需要大規(guī)模迅速修改配置,估計(jì)運(yùn)維人員也只能兩手一攤了迟杂。
所以刽沾,綜合以上幾個(gè)要素,我們 需要一個(gè)統(tǒng)一的配置中心來(lái)管理微服務(wù)的配置排拷。
配置中心的一般模樣
那么侧漓,我們應(yīng)該需要一個(gè)什么樣的配置中心呢?
接下來(lái)就以 開(kāi)源配置中心 Apollo 為例监氢,來(lái)看一下配置中心的一般模樣布蔗。
如前面所論述的:配置需要治理,所以配置中心需要具備完善的治理能力浪腐,比如:
統(tǒng)一管理不同環(huán)境纵揍、不同集群的配置
支持灰度發(fā)布
支持已發(fā)布的配置回滾
完善的權(quán)限管理、操作審計(jì)日志
Apollo 配置中心的管理界面如下圖所示议街,可以發(fā)現(xiàn)相應(yīng)的治理功能還是非常齊全的泽谨。
配置即『控制』,所以在一定程度上特漩,配置中心已經(jīng)成為了微服務(wù)的大腦吧雹,作為大腦,可用性顯然是要求非常高的拾稳。
接下來(lái)我們一起看一下 Apollo 是怎么實(shí)現(xiàn)高可用的吮炕。
Apollo at a glance
如下即是 Apollo 的基礎(chǔ)模型:
用戶在配置中心對(duì)配置進(jìn)行修改并發(fā)布
配置中心通知 Apollo 客戶端有配置更新
Apollo 客戶端從配置中心拉取最新的配置腊脱、更新本地配置并通知到應(yīng)用
服務(wù)端高可用
上圖簡(jiǎn)要描述了 Apollo 的服務(wù)端設(shè)計(jì)访得,我們可以從下往上看:
首先最下面是一個(gè) DB,我們的配置是放在 DB 里的陕凹,然后在 DB 之上有兩個(gè)服務(wù):Config Service 和 Admin Service悍抑;
Config Service 提供配置的讀取、推送等功能杜耙,服務(wù)對(duì)象是 Apollo 客戶端搜骡;
Admin Service 提供配置的修改、發(fā)布等功能佑女,服務(wù)對(duì)象是 Apollo Portal(管理界面)记靡;
Config Service 和 Admin Service 都是多實(shí)例谈竿、無(wú)狀態(tài)部署,所以需要將自己注冊(cè)到 Eureka 中并保持心跳摸吠;
在 Eureka 之上我們架了一層 Meta Server 用于封裝 Eureka 的服務(wù)發(fā)現(xiàn)接口空凸,主要是為了讓客戶端和 Eureka 解耦;
Client 通過(guò)域名訪問(wèn) Meta Server 獲取 Config Service 服務(wù)列表(IP+Port)寸痢,而后直接通過(guò) IP+Port 訪問(wèn)服務(wù)呀洲,同時(shí)在 Client 側(cè)會(huì)做 load balance、錯(cuò)誤重試啼止;
Portal 通過(guò)域名訪問(wèn) Meta Server 獲取 Admin Service 服務(wù)列表(IP+Port)道逗,而后直接通過(guò) IP+Port 訪問(wèn)服務(wù),同時(shí)在 Portal 側(cè)會(huì)做 load balance献烦、錯(cuò)誤重試滓窍;
為了簡(jiǎn)化部署,我們實(shí)際上會(huì)把 Config Service仿荆、Eureka 和 Meta Server 三個(gè)邏輯角色部署在同一個(gè) JVM 進(jìn)程中贰您;
通過(guò)上述的設(shè)計(jì),可以看到整個(gè)服務(wù)端是無(wú)單點(diǎn)拢操,有效地保證了服務(wù)端的可用性锦亦。
客戶端高可用
上圖簡(jiǎn)要描述了 Apollo 客戶端的實(shí)現(xiàn)原理:
客戶端和服務(wù)端保持了一個(gè)長(zhǎng)連接,從而能第一時(shí)間獲得配置更新的推送令境。(通過(guò) Http Long Polling 實(shí)現(xiàn))杠园;
-
客戶端還會(huì)定時(shí)從 Apollo 配置中心服務(wù)端拉取應(yīng)用的最新配置;
這是一個(gè) fallback 機(jī)制舔庶,為了防止推送機(jī)制失效導(dǎo)致配置不更新抛蚁;
客戶端定時(shí)拉取會(huì)上報(bào)本地版本,所以一般情況下惕橙,對(duì)于定時(shí)拉取的操作瞧甩,服務(wù)端都會(huì)返回 304 - Not Modified。
客戶端從 Apollo 配置中心服務(wù)端獲取到應(yīng)用的最新配置后弥鹦,會(huì)保存在內(nèi)存中肚逸,所以我們的應(yīng)用程序來(lái)獲取配置的時(shí)候其實(shí)始終是從內(nèi)存中獲取的;
-
客戶端還會(huì)把從服務(wù)端獲取到的配置在本地文件系統(tǒng)緩存一份彬坏;
這主要是為了容災(zāi)朦促,假設(shè)應(yīng)用程序重啟的時(shí)候,恰好遠(yuǎn)端服務(wù)全掛了栓始,或者網(wǎng)絡(luò)有故障务冕,應(yīng)用程序依然能從本地恢復(fù)配置。
通過(guò)這種推拉結(jié)合的機(jī)制幻赚,以及內(nèi)存和本地文件雙緩存的方式禀忆,有效地保證了客戶端的可用性臊旭。
可用性場(chǎng)景舉例
配置即『控制』,所以我們希望我們的控制指令能迅速箩退、準(zhǔn)確地傳達(dá)到應(yīng)用程序巍扛,我們來(lái)看看 Apollo 是如何實(shí)現(xiàn)實(shí)時(shí)性的。
上圖簡(jiǎn)要描述了配置發(fā)布的大致過(guò)程:
用戶在 Portal 操作配置發(fā)布乏德;
Portal 調(diào)用 Admin Service 的接口操作發(fā)布撤奸;
Admin Service 發(fā)布配置后,發(fā)送 ReleaseMessage 給各個(gè) Config Service喊括;
Config Service 收到 ReleaseMessage 后胧瓜,通知對(duì)應(yīng)的客戶端。
發(fā)送 ReleaseMessage 的實(shí)現(xiàn)方式
Admin Service 在配置發(fā)布后郑什,需要通知所有的 Config Service 有配置發(fā)布府喳,從而 Config Service 可以通知對(duì)應(yīng)的客戶端來(lái)拉取最新的配置。
從概念上來(lái)看蘑拯,這是一個(gè)典型的消息使用場(chǎng)景钝满,Admin Service 作為 producer 發(fā)出消息,各個(gè) Config Service 作為 consumer 消費(fèi)消息申窘。通過(guò)一個(gè)消息組件(Message Queue)就能很好的實(shí)現(xiàn) Admin Service 和 Config Service 的解耦弯蚜。
在實(shí)現(xiàn)上,考慮到 Apollo 的實(shí)際使用場(chǎng)景剃法,以及為了盡可能減少外部依賴碎捺,我們沒(méi)有采用外部的消息中間件,而是通過(guò)數(shù)據(jù)庫(kù)實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的消息隊(duì)列贷洲。
實(shí)現(xiàn)方式如下:
Admin Service 在配置發(fā)布后會(huì)往 ReleaseMessage 表插入一條消息記錄收厨,消息內(nèi)容就是配置發(fā)布的 AppId+Cluster+Namespace
Config Service 有一個(gè)線程會(huì)每秒掃描一次 ReleaseMessage 表,看看是否有新的消息記錄
Config Service 如果發(fā)現(xiàn)有新的消息記錄优构,解析得到配置發(fā)布的 AppId+Cluster+Namespace 后诵叁,通知到對(duì)應(yīng)的客戶端
示意圖如下:
如何讓微服務(wù)更『智能』?
接下來(lái)我們來(lái)看一下結(jié)合配置中心钦椭,我們能做哪些有趣的事情拧额,讓微服務(wù)更智能。
發(fā)布開(kāi)關(guān)
發(fā)布開(kāi)關(guān)一般用于發(fā)布過(guò)程中玉凯,比如:
有些新功能依賴于其它系統(tǒng)的新接口势腮,而其它系統(tǒng)的發(fā)布周期未必和自己的系統(tǒng)一致联贩,可以加個(gè)發(fā)布開(kāi)關(guān)漫仆,默認(rèn)把該功能關(guān)閉,等依賴系統(tǒng)上線后再打開(kāi)泪幌;
有些新功能有較大風(fēng)險(xiǎn)盲厌,可以加個(gè)發(fā)布開(kāi)關(guān)署照,上線后一旦有問(wèn)題可以迅速關(guān)閉。
需要注意的是吗浩,發(fā)布開(kāi)關(guān)應(yīng)該是短暫存在的(1-2 周)建芙,一旦功能穩(wěn)定后需要及時(shí)清除開(kāi)關(guān)代碼。
實(shí)驗(yàn)開(kāi)關(guān)
實(shí)驗(yàn)開(kāi)關(guān)通常用于對(duì)比測(cè)試或功能測(cè)試懂扼,比如:
-
A/B 測(cè)試
針對(duì)特定用戶應(yīng)用新的推薦算法禁荸;
針對(duì)特定百分比的用戶使用新的下單流程;
-
QA 測(cè)試
有些重大功能已經(jīng)對(duì)外宣稱在某年某日發(fā)布
可以事先發(fā)到生產(chǎn)環(huán)境阀湿,只對(duì)內(nèi)部用戶打開(kāi)赶熟,測(cè)試沒(méi)問(wèn)題后按時(shí)對(duì)全部用戶開(kāi)放
實(shí)驗(yàn)開(kāi)關(guān)應(yīng)該也是短暫存在的,一旦實(shí)驗(yàn)結(jié)束了需要及時(shí)清除實(shí)驗(yàn)開(kāi)關(guān)代碼陷嘴。
運(yùn)維開(kāi)關(guān)
運(yùn)維開(kāi)關(guān)通常用于提升系統(tǒng)穩(wěn)定性映砖,比如:
大促前可以把一些非關(guān)鍵功能關(guān)閉來(lái)提升系統(tǒng)容量;
當(dāng)系統(tǒng)出現(xiàn)問(wèn)題時(shí)可以關(guān)閉非關(guān)鍵功能來(lái)保證核心功能正常工作灾挨。
運(yùn)維開(kāi)關(guān)可能會(huì)長(zhǎng)期存在邑退,而且一般會(huì)涉及多個(gè)系統(tǒng),所以需要提前規(guī)劃劳澄。
限流
服務(wù)就像高速公路一樣地技,在正常情況下非常通暢,不過(guò)一旦流量突增(比如大促秒拔、遭受 DDOS 攻擊)時(shí)乓土,如果沒(méi)有做好限流,就會(huì)導(dǎo)致系統(tǒng)整個(gè)被沖垮溯警,所有用戶都無(wú)法訪問(wèn)趣苏。
正常的高速公路
超出容量的高速公路
所以我們需要限流機(jī)制來(lái)應(yīng)對(duì)此類問(wèn)題,一般的做法是在網(wǎng)關(guān)或 RPC 框架層添加限流邏輯梯轻,結(jié)合配置中心的動(dòng)態(tài)推送能力實(shí)現(xiàn)動(dòng)態(tài)調(diào)整限流規(guī)則配置食磕。
黑白名單
對(duì)于一些關(guān)鍵服務(wù),哪怕是在內(nèi)網(wǎng)環(huán)境中一般也會(huì)對(duì)調(diào)用方有所限制喳挑,比如:
有敏感信息的服務(wù)可以通過(guò)配置白名單來(lái)限制只有某些應(yīng)用或 IP 才能調(diào)用
某個(gè)調(diào)用方代碼有問(wèn)題導(dǎo)致超大量調(diào)用彬伦,對(duì)服務(wù)穩(wěn)定性產(chǎn)生了影響,可以通過(guò)配置黑名單來(lái)暫時(shí)屏蔽這個(gè)調(diào)用方或 IP
一般的做法是在 RPC 框架層添加校驗(yàn)邏輯伊诵,結(jié)合配置中心的動(dòng)態(tài)推送能力來(lái)實(shí)現(xiàn)動(dòng)態(tài)調(diào)整黑白名單配置单绑。
數(shù)據(jù)庫(kù)的遷移也是挺普遍的,比如:原來(lái)使用的 SQL Server曹宴,現(xiàn)在需要遷移到 MySQL搂橙,這種情況就可以結(jié)合配置中心來(lái)實(shí)現(xiàn)平滑遷移:
單寫(xiě) SQL Server,100% 讀 SQL Server笛坦;
初始化 MySQL区转;
雙寫(xiě) SQL Server 和 MySQL苔巨,100% 讀 SQL Server;
線下校驗(yàn)废离、補(bǔ)齊 MySQL 數(shù)據(jù)侄泽;
雙寫(xiě) SQL Server 和 MySQL,90% 讀 SQL Server蜻韭,10% 讀 MySQL悼尾;
雙寫(xiě) SQL Server 和 MySQL,100% 讀 MySQL肖方;
單寫(xiě) MySQL诀豁,100% 讀 MySQL;
切換完成窥妇。
上述的讀寫(xiě)開(kāi)關(guān)和比例配置都可以通過(guò)配置中心實(shí)現(xiàn)動(dòng)態(tài)調(diào)整舷胜。
服務(wù)運(yùn)行過(guò)程中,經(jīng)常會(huì)遇到需要通過(guò)日志來(lái)排查定位問(wèn)題的情況活翩,然而這里卻有個(gè)兩難:
如果日志級(jí)別很高(如:ERROR)烹骨,可能對(duì)排查問(wèn)題也不會(huì)有太大幫助
如果日志級(jí)別很低(如:DEBUG),日常運(yùn)行會(huì)帶來(lái)非常大的日志量材泄,造成系統(tǒng)性能下降
為了兼顧性能和排查問(wèn)題沮焕,我們可以借助于日志組件和配置中心實(shí)現(xiàn)日志級(jí)別動(dòng)態(tài)調(diào)整。
以 Spring Boot 和 Apollo 結(jié)合為例:
@ApolloConfigChangeListener
private void onChange(ConfigChangeEvent changeEvent) {
refreshLoggingLevels(changeEvent.changedKeys());
}
private void refreshLoggingLevels(Set<String> changedKeys) {
boolean loggingLevelChanged = false;
for (String changedKey : changedKeys) {
if (changedKey.startsWith("logging.level.")) {
loggingLevelChanged = true;
break;
}
}
if (loggingLevelChanged) {
// refresh logging levels
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changedKeys));
}
}
詳細(xì)樣例代碼可以參考:
https://github.com/ctripcorp/apollo-use-cases/tree/master/spring-cloud-logger
網(wǎng)關(guān)的核心功能之一就是路由轉(zhuǎn)發(fā)拉宗,而其中的路由信息也是經(jīng)常會(huì)需要變化的峦树,我們也可以結(jié)合配置中心實(shí)現(xiàn)動(dòng)態(tài)更新路由信息。
以 Spring Cloud Zuul 和 Apollo 結(jié)合為例:
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
boolean zuulPropertiesChanged = false;
for (String changedKey : changeEvent.changedKeys()) {
if (changedKey.startsWith("zuul.")) {
zuulPropertiesChanged = true;
break;
}
}
if (zuulPropertiesChanged) {
refreshZuulProperties(changeEvent);
}
}
private void refreshZuulProperties(ConfigChangeEvent changeEvent) {
// rebind configuration beans, e.g. ZuulProperties
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));
// refresh routes
this.applicationContext.publishEvent(new RoutesRefreshedEvent(routeLocator));
}
詳細(xì)樣例代碼可以參考:
https://github.com/ctripcorp/apollo-use-cases/tree/master/spring-cloud-zuul
數(shù)據(jù)庫(kù)是應(yīng)用運(yùn)行過(guò)程中的一個(gè)非常重要的資源旦事,承擔(dān)了非常重要的角色魁巩。
在運(yùn)行過(guò)程中,我們會(huì)遇到各種不同的場(chǎng)景需要讓?xiě)?yīng)用程序切換數(shù)據(jù)庫(kù)連接姐浮,比如:數(shù)據(jù)庫(kù)維護(hù)谷遂、數(shù)據(jù)庫(kù)宕機(jī)主從切換等。
切換過(guò)程如下圖所示:
以 Spring Boot 和 Apollo 結(jié)合為例:
@Configuration
public class RefreshableDataSourceConfiguration {
@Bean
public DynamicDataSource dataSource(DataSourceManager dataSourceManager) {
DataSource actualDataSource = dataSourceManager.createDataSource();
return new DynamicDataSource(actualDataSource);
}
}
public class DynamicDataSource implements DataSource {
private final AtomicReference<DataSource> dataSourceAtomicReference;
public DynamicDataSource(DataSource dataSource) {
dataSourceAtomicReference = new AtomicReference<>(dataSource);
}
// set the new data source and return the previous one
public DataSource setDataSource(DataSource newDataSource){
return dataSourceAtomicReference.getAndSet(newDataSource);
}
@Override
public Connection getConnection() throws SQLException {
return dataSourceAtomicReference.get().getConnection();
}
...
}
@ApolloConfigChangeListener
public void onChange(ConfigChangeEvent changeEvent) {
boolean dataSourceConfigChanged = false;
for (String changedKey : changeEvent.changedKeys()) {
if (changedKey.startsWith("spring.datasource.")) {
dataSourceConfigChanged = true;
break;
}
}
if (dataSourceConfigChanged) {
refreshDataSource(changeEvent.changedKeys());
}
}
private synchronized void refreshDataSource(Set<String> changedKeys) {
try {
// rebind configuration beans, e.g. DataSourceProperties
this.applicationContext.publishEvent(new EnvironmentChangeEvent(changedKeys));
DataSource newDataSource = dataSourceManager.createAndTestDataSource();
DataSource oldDataSource = dynamicDataSource.setDataSource(newDataSource);
asyncTerminate(oldDataSource);
} catch (Throwable ex) {
logger.error("Refreshing data source failed", ex);
}
}
詳細(xì)樣例代碼可以參考:
https://github.com/ctripcorp/apollo-use-cases/tree/master/dynamic-datasource
最佳實(shí)踐
公共組件是指那些發(fā)布給其它應(yīng)用使用的客戶端代碼卖鲤,比如 RPC 客戶端肾扰、DAL 客戶端等。
這類組件一般是由單獨(dú)的團(tuán)隊(duì)(如中間件團(tuán)隊(duì))開(kāi)發(fā)蛋逾、維護(hù)集晚,但是運(yùn)行時(shí)是在業(yè)務(wù)實(shí)際應(yīng)用內(nèi)的,所以本質(zhì)上可以認(rèn)為是應(yīng)用的一部分区匣。
這類組件的特殊之處在于大部分的應(yīng)用都會(huì)直接使用中間件團(tuán)隊(duì)提供的默認(rèn)值偷拔,少部分的應(yīng)用需要根據(jù)自己的實(shí)際情況對(duì)默認(rèn)值進(jìn)行調(diào)整。
比如數(shù)據(jù)庫(kù)連接池的最小空閑連接數(shù)量(minimumIdle),出于對(duì)數(shù)據(jù)庫(kù)資源的保護(hù)条摸,DBA 要求將全公司默認(rèn)的 minimumIdle 設(shè)為 1,對(duì)大部分的應(yīng)用可能都適用铸屉,不過(guò)有些核心 / 高流量應(yīng)用可能覺(jué)得太小钉蒲,需要設(shè)為 10。
針對(duì)這種情況彻坛,可以借助于 Apollo 提供的 Namespace 實(shí)現(xiàn):
-
中間件團(tuán)隊(duì)創(chuàng)建一個(gè)名為
dal
的公共 Namespace顷啼,設(shè)置全公司的數(shù)據(jù)庫(kù)連接池默認(rèn)配置minimumIdle = 1 maximumPoolSize = 20
dal 組件的代碼會(huì)讀取
dal
公共 Namespace 的配置對(duì)大部分的應(yīng)用由于默認(rèn)配置已經(jīng)適用,所以不用做任何事情
對(duì)于少量核心 / 高流量應(yīng)用如果需要調(diào)整 minimumIdle 的值昌屉,只需要關(guān)聯(lián)
dal
公共 Namespace钙蒙,然后對(duì)需要覆蓋的配置做調(diào)整即可,調(diào)整后的配置僅對(duì)該應(yīng)用自己生效
minimumIdle = 10
通過(guò)這種方式的好處是不管是中間件團(tuán)隊(duì)间驮,還是應(yīng)用開(kāi)發(fā)躬厌,都可以靈活地動(dòng)態(tài)調(diào)整公共組件的配置。
對(duì)于重要的配置一定要做灰度發(fā)布竞帽,先在一臺(tái)或多臺(tái)機(jī)器上生效后觀察效果扛施,如果沒(méi)有問(wèn)題再推給所有的機(jī)器。
對(duì)于公共組件的配置屹篓,建議先在一個(gè)或多個(gè)應(yīng)用上生效后觀察效果疙渣,沒(méi)有問(wèn)題再推給所有的應(yīng)用。
生產(chǎn)環(huán)境建議啟用發(fā)布審核功能堆巧,簡(jiǎn)單而言就是如果某個(gè)人修改了配置妄荔,那么必須由另一個(gè)人審核后才可以發(fā)布,以避免由于頭腦不清醒谍肤、手一抖之類的造成生產(chǎn)事故啦租。
結(jié) 語(yǔ)
本文主要介紹了以下幾方面:
-
為什么需要配置中心?
配置即『控制』
配置需要治理
微服務(wù)帶來(lái)的配置復(fù)雜性
-
配置中心的一般模樣
以 Apollo 為例子荒揣,介紹了配置中心所具備的特征
介紹了 Apollo 是如何實(shí)現(xiàn)高可用和實(shí)時(shí)性的
-
如何讓微服務(wù)更『智能』刷钢?
通過(guò)幾個(gè)案例,分享了如何借助于配置中心使微服務(wù)更『智能』
-
配置中心的最佳實(shí)踐
公共組件的配置
灰度發(fā)布
發(fā)布審核
最后乳附,希望大家在平時(shí)工作中都能用好配置中心内地,更好地服務(wù)于業(yè)務(wù)場(chǎng)景,使微服務(wù)更『智能』赋除,實(shí)現(xiàn)從青銅到王者的跨越阱缓!