摘要:我們是不是很好奇配置中心如何做到實(shí)時(shí)更新并且通知到客戶端的這也是一個(gè)面試中經(jīng)常會(huì)問(wèn)到的題目。客戶端得到狀態(tài)碼是并且會(huì)根據(jù)立即去服務(wù)端拉取最新的配置。
記得我們那時(shí)候剛開(kāi)始學(xué)習(xí)Java
的時(shí)候都只是一個(gè)單體項(xiàng)目,項(xiàng)目里面的配置基本都是寫(xiě)在項(xiàng)目里面的properties文件中,比如數(shù)據(jù)庫(kù)配置啥的,各種邏輯開(kāi)關(guān),一旦這些配置修改了,還需要重啟項(xiàng)目這修改才會(huì)生效。隨著各種微服務(wù)的誕生,服務(wù)的拆分也越來(lái)越細(xì),可能涉及的服務(wù)成千上百,服務(wù)基本也是集群部署,這樣再去一個(gè)一個(gè)項(xiàng)目修改配置,然后重啟這顯然是行不通的。所以分布式配置中心就誕生了,現(xiàn)在開(kāi)源的分布式配置中心也挺多的比如:開(kāi)源分布式配置中心有很多,比如spring-cloud/spring-cloud-config、淘寶/diamond、百度/disconf、攜程/apollo、netflix/archaius、Qconf、XDiamond、naco
s等等。我們是不是很好奇配置中心如何做到實(shí)時(shí)更新并且通知到客戶端的這也是一個(gè)面試中經(jīng)常會(huì)問(wèn)到的題目。下面我們就以apollo為例吧去分析分析它是如何實(shí)現(xiàn)的。為什么選擇Apollo
來(lái)分析列?因?yàn)楝F(xiàn)在的公司就在使用它作為配置中心。雖然Apollo
是攜程開(kāi)源的,但是攜程內(nèi)部也不用它。
要去了解一個(gè)玩意,就要先會(huì)去使用它。它的使用基本上很簡(jiǎn)單。雖然使用簡(jiǎn)單方便,但是它的設(shè)計(jì)還是挺復(fù)雜的,下面我們看一個(gè)它官網(wǎng)提供的架構(gòu)圖,是不是挺復(fù)雜的。
通過(guò)上述架構(gòu)圖我們可以看到ConfigService、AdminService、Client、Portal、 Meta Server、Eureka這幾個(gè)模塊,主要的還是前面四個(gè)模塊Meta Server、Eureka這兩個(gè)模塊只是Apollo本身內(nèi)部所需要的輔助模塊,我們暫時(shí)可以不需要關(guān)注它。
介紹完了上面這些Apollo
組成的模塊回到正題,配置中心如何做到實(shí)時(shí)更新并且到客戶端如何感知配置被更新了?看這個(gè)問(wèn)題之前我們先回顧下每到周末我們?nèi)ト藲獗容^旺的餐廳吃飯的時(shí)候流程是什么樣的?
client
)告訴它某某你的應(yīng)用的配置被修改了,原來(lái)的值是啥被修改后的值是啥?還是說(shuō)客戶端(Client)每隔多久去問(wèn)下服務(wù)端我的配置有沒(méi)有被修改呀?如果是你你會(huì)怎么選擇列?你也許會(huì)說(shuō)我肯定兩種方式都要呀!小朋友才會(huì)做選擇?再回到我們使用apollo
的時(shí)候我們應(yīng)用里面引入的Apollo
的Client
在我們應(yīng)用啟動(dòng)的時(shí)候會(huì)有一個(gè)線程每隔5s
向服務(wù)短發(fā)起一個(gè)http
請(qǐng)求,不過(guò)這個(gè)http
請(qǐng)求是不會(huì)立即返回的。它是一個(gè)長(zhǎng)鏈接如果配置沒(méi)有被更新,這個(gè)請(qǐng)求會(huì)被阻塞掛起,這個(gè)實(shí)現(xiàn)掛起的方式是通過(guò)Spring
的DeferredResult
來(lái)實(shí)現(xiàn)的,如果對(duì)這個(gè)Spring
的DeferredResult
不是很了解的推薦看下這個(gè)文章《5種SpringMvc的異步處理方式你都了解嗎?》
掛起60s后會(huì)返回HTTP
狀態(tài)碼為304
給到客戶端,如果再阻塞的過(guò)程中服務(wù)端配置有更新,這個(gè)Http請(qǐng)求會(huì)立馬返回,并且把變化的nameSpace信息返回出去,并且返回的http的狀態(tài)碼是200。客戶端得到狀態(tài)碼是200并且會(huì)根據(jù)nameSpace立即去服務(wù)端拉取最新的配置。
這里其實(shí)有一個(gè)問(wèn)題,為什么不直接在長(zhǎng)鏈接中返回變更后的結(jié)果,而是返回一個(gè)變更的通知,需要客戶端根據(jù)這個(gè)變更通知立即去拉取新的配置?
感興趣的可以參考下這個(gè)issue :https://github.com/apolloconfig/apollo/issues/652
這樣推送消息就是有狀態(tài)了,做不到冪等了,會(huì)帶來(lái)很多問(wèn)題。目前推送是單連接走h(yuǎn)ttp的,所以問(wèn)題可能不大,不過(guò)在設(shè)計(jì)上而言是有這個(gè)問(wèn)題的,比如如果推送是走的tcp長(zhǎng)連接的話。另外,長(zhǎng)輪詢和推送之間也會(huì)有沖突,如果連續(xù)兩次配置變化,就可能造成雙寫(xiě)。還有一點(diǎn),就是保持邏輯的簡(jiǎn)單,目前的做法推送只負(fù)責(zé)做簡(jiǎn)單的通知,不需要去計(jì)算客戶端的配置應(yīng)該是什么,因?yàn)橛?jì)算邏輯挺復(fù)雜的,需要考慮集群,關(guān)聯(lián),灰度等,總而言之,就是在滿足冪等性,實(shí)時(shí)性的基礎(chǔ)上保持設(shè)計(jì)的簡(jiǎn)單。
這樣是不是就是很完美了,客戶端可以實(shí)時(shí)接收到配置的更新。但是客戶端如果接收服務(wù)端的更新內(nèi)容處理失敗,比如服務(wù)異常或者空指針的時(shí)候。這時(shí)候我們的客戶端配置如果不重啟是不是永遠(yuǎn)都不會(huì)被更新了。沒(méi)關(guān)系這種情況apollo
也幫你想到啦,你既然告訴我更新失敗,那我就自己每隔一段時(shí)間主動(dòng)去把我所有的配置都拉到客服端,拉回客服端之后和客戶端的緩存配置做比較,如果一致直接結(jié)束,不一致就更新客戶端的緩存,并且還會(huì)去異步更新本地文件。通過(guò)定時(shí)任務(wù)的補(bǔ)充,可以讓配置達(dá)到最終的一致性。
主動(dòng)輪詢,和定時(shí)任務(wù)全量拉取配置是不是就萬(wàn)無(wú)一失呢?只要涉及到分布式我們就要考慮到其他系統(tǒng)的宕機(jī),比如哪一天挖機(jī)直接把部署Apollo的機(jī)房的光纖給挖斷了,這樣整個(gè)配置服務(wù)直接掛了,這時(shí)候主動(dòng)輪詢以及定時(shí)任務(wù)都沒(méi)法起到作用了。是不是拉取不了配置,整個(gè)我們的客戶端應(yīng)用也要跟著受影響列,我們的配置基本上是改動(dòng)的頻率也是比較小的,即使我們的配置中心掛掉了,我們還有一份本地文件系統(tǒng)來(lái)兜底,這個(gè)文件目錄默認(rèn)是/opt/data或C:/opt/data,
所以即使配置中心掛了,對(duì)應(yīng)用的影響也比較小。因?yàn)樗€會(huì)去讀取本地文件來(lái)兜底。
到現(xiàn)在為止我們應(yīng)該知道Apollo客戶端是如何感知服務(wù)端配置更新了的把?
Apollo ConfigServer
端,如果Apollo ConfigServer
端有配置更改會(huì)告訴應(yīng)用端有配置修改,讓客戶端立馬去拉取全量的配置,并且把配置更新到本地緩存,并且還會(huì)異步去更新本地文件緩存。5min
執(zhí)行一次的定時(shí)任務(wù),去拉取全量的配置。拉回配置之后也是對(duì)比本地緩存和遠(yuǎn)程是否一致,如果不一致則更新本地進(jìn)程緩存為遠(yuǎn)程的,同時(shí)還去異步更新下本地文件。文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/123979.html
摘要:我們是不是很好奇配置中心如何做到實(shí)時(shí)更新并且通知到客戶端的這也是一個(gè)面試中經(jīng)常會(huì)問(wèn)到的題目。雖然是攜程開(kāi)源的,但是攜程內(nèi)部也不用它。客戶端得到狀態(tài)碼是并且會(huì)根據(jù)立即去服務(wù)端拉取最新的配置。通過(guò)定時(shí)任務(wù)的補(bǔ)充,可以讓配置達(dá)到最終的一致性。 引言記得我們那時(shí)候剛開(kāi)始學(xué)習(xí)Java的時(shí)候都只是一個(gè)單體項(xiàng)目,項(xiàng)目里面的配...
摘要:比如使用的時(shí)候指定使用哪個(gè)環(huán)境的配置在微服務(wù)架構(gòu)下,服務(wù)的數(shù)量會(huì)比之前的單體應(yīng)用多,部署的節(jié)點(diǎn)數(shù)量也會(huì)很多。今天主要是講下在中如何對(duì)接進(jìn)行配置管理。 問(wèn)題背景 在實(shí)際工作中,我們的開(kāi)發(fā)環(huán)境,測(cè)試環(huán)境,生產(chǎn)環(huán)境對(duì)應(yīng)的 Mysql 數(shù)據(jù)庫(kù),Redis 這些信息都不一樣,每個(gè)環(huán)境都有對(duì)應(yīng)的一套配置,在 Spring Boot 中我們通常會(huì)編寫(xiě)多個(gè)配置文件,也就是每個(gè)環(huán)境一個(gè)配置文件。 比如:...
摘要:基于的動(dòng)態(tài)配置推送。對(duì)于任務(wù)中心這種多任務(wù)平臺(tái)型的配置,有一定影響。基于回調(diào)和配置的擴(kuò)展點(diǎn)流程共建在建中通過(guò)擴(kuò)展點(diǎn)共建方式,將流程編排的能力,暴露給內(nèi)外部的開(kāi)發(fā)者,完成任務(wù)中心的共建。 一、聊聊本文想說(shuō)什么: ??為更好幫助商家的會(huì)員快速成長(zhǎng),保持用戶活性,完善用戶的成長(zhǎng)體系,有贊用戶中心-會(huì)員成長(zhǎng)團(tuán)隊(duì)基于現(xiàn)有的業(yè)務(wù)場(chǎng)景,設(shè)計(jì)了一套較完備任務(wù)中心系統(tǒng)。同時(shí)也有很多通用技術(shù)組件能夠落地。...
摘要:零為何要學(xué)源碼簡(jiǎn)單,是我現(xiàn)在看起來(lái)最簡(jiǎn)單的源碼不會(huì)像封裝了一層又一層,把人繞暈,而沒(méi)有那么多封裝,上手快,我們學(xué)習(xí)就應(yīng)該從簡(jiǎn)單的開(kāi)始憑什么非要去學(xué)封的像粽子一樣的源碼,我們就是要去學(xué)簡(jiǎn)簡(jiǎn)單單,平時(shí)樸素,接地氣的源碼最接近業(yè)務(wù)代碼的源碼。 零 為何要學(xué)apollo源碼 1 簡(jiǎn)單,Apollo是我現(xiàn)在看起來(lái)最簡(jiǎn)單的源碼不會(huì)像spring封裝了一層又一層,把人繞暈,而apollo沒(méi)有那么多封...
摘要:這樣做的方式是簡(jiǎn)單,缺點(diǎn)是無(wú)法及時(shí)獲取變更推模式規(guī)則中心統(tǒng)一推送,客戶端通過(guò)注冊(cè)監(jiān)聽(tīng)器的方式時(shí)刻監(jiān)聽(tīng)變化,比如使用等配置中心。 在前面的學(xué)習(xí)過(guò)程中,Sentinel 的規(guī)則,也就是我們之前定義的限流規(guī)則,是通過(guò)代碼的方式定義好的。這是初始化時(shí)需要做的事情,Sentinel 提供了基于API的方式修改規(guī)則: FlowRuleManager.loadRules(List rules); /...
閱讀 4913·2023-04-25 18:47
閱讀 2673·2021-11-19 11:33
閱讀 3445·2021-11-11 16:54
閱讀 3101·2021-10-26 09:50
閱讀 2540·2021-10-14 09:43
閱讀 665·2021-09-03 10:47
閱讀 671·2019-08-30 15:54
閱讀 1498·2019-08-30 15:44