?Hadoop是一個(gè)技術(shù)生態(tài)圈,zookeeper是hadoop生態(tài)圈里一個(gè)非常重要的技術(shù)。
當(dāng)我研究學(xué)習(xí)hadoop的相關(guān)技術(shù)時(shí)候,有兩塊知識(shí)曾經(jīng)讓我十分的困惑,一個(gè)是hbase河哑,一個(gè)就是zookeeper。
hbase的困惑源自于它在顛覆了我對(duì)數(shù)據(jù)庫(kù)建模的理解龟虎,而zookeeper的困惑卻是我無(wú)法理解它到底是干嘛的璃谨。
遠(yuǎn)程調(diào)用服務(wù)的架構(gòu)設(shè)計(jì)總述
首先我們要再深入理解下為什么應(yīng)用軟件服務(wù)里需要一個(gè)遠(yuǎn)程調(diào)用服務(wù),遠(yuǎn)程調(diào)用服務(wù)解決了軟件設(shè)計(jì)中的什么問(wèn)題遣总,它的架構(gòu)設(shè)計(jì)又有什么理論根據(jù)了?
3.0版本的網(wǎng)站架構(gòu)帶來(lái)了新的網(wǎng)站架構(gòu)總圖睬罗,如下所示:
有了遠(yuǎn)程調(diào)用服務(wù),我們可以做到業(yè)務(wù)級(jí)別的集群旭斥。
例如:一個(gè)制造企業(yè)容达,一般都會(huì)有采購(gòu)業(yè)務(wù),生產(chǎn)業(yè)務(wù)垂券、銷售業(yè)務(wù)以及財(cái)務(wù)業(yè)務(wù)花盐。按照傳統(tǒng)的思路我們都會(huì)給每個(gè)業(yè)務(wù)獨(dú)立開發(fā)一個(gè)系統(tǒng),如果引用了遠(yuǎn)程調(diào)用服務(wù)菇爪,我們可以將這些業(yè)務(wù)都做成獨(dú)立的服務(wù)算芯,這些服務(wù)組成業(yè)務(wù)集群,而這些服務(wù)都是用統(tǒng)一的遠(yuǎn)程調(diào)用服務(wù)作為操作的入口凳宙。
換句話說(shuō)不管什么樣的服務(wù)對(duì)于調(diào)用者來(lái)說(shuō)都是統(tǒng)一的熙揍,這樣前端的調(diào)用者可以做到應(yīng)用的統(tǒng)一,所謂的應(yīng)用的統(tǒng)一淘寶網(wǎng)站是最典型的代表氏涩,我們?cè)谝粋€(gè)同一的網(wǎng)站里可以操作各種不同的應(yīng)用届囚,而不會(huì)發(fā)生因?yàn)閼?yīng)用的不同我們就得重新訪問(wèn)新的地址或者重新登錄到另外一個(gè)系統(tǒng)里做其他業(yè)務(wù)的操作。
而服務(wù)端這邊是尖,完全可以擺脫傳統(tǒng)的客戶端和服務(wù)端耦合的開發(fā)意系,增強(qiáng)了整個(gè)服務(wù)端的專業(yè)性和穩(wěn)定性,這樣更易于服務(wù)端的擴(kuò)展性和可維護(hù)性饺汹。
如果服務(wù)端之間也需要相互調(diào)用也可以通過(guò)遠(yuǎn)程調(diào)用服務(wù)實(shí)現(xiàn)蛔添,由于遠(yuǎn)程調(diào)用服務(wù)的統(tǒng)一性,這樣就避免了服務(wù)調(diào)用之間報(bào)文和調(diào)用方式的不統(tǒng)一,規(guī)范了整個(gè)開發(fā)的流程迎瞧。
如果遠(yuǎn)程調(diào)用服務(wù)還有負(fù)載均衡功能夸溶,整個(gè)服務(wù)集群就變成了一個(gè)私有的云,所以說(shuō)遠(yuǎn)程調(diào)用服務(wù)是云計(jì)算的重要組成部分凶硅,這個(gè)說(shuō)法一點(diǎn)都不為過(guò)蜘醋。
遠(yuǎn)程調(diào)用服務(wù)的理論依據(jù)是什么,這個(gè)問(wèn)題的表述可能有點(diǎn)問(wèn)題咏尝,其實(shí)我要講的是遠(yuǎn)程調(diào)用服務(wù)的技術(shù)原型就是SOA(Service-Oriented Architecture)。
在云計(jì)算出現(xiàn)前啸罢,SOA曾一度是IT的技術(shù)熱點(diǎn)编检,雖然之后很多人說(shuō)中國(guó)的SOA做的一點(diǎn)不好,就和早年的DHTML一樣扰才,詬病遠(yuǎn)多于贊賞允懂,寫本文時(shí)候我在京東里搜索了下SOA,從書籍的出版日期和書籍評(píng)價(jià)數(shù)就可以看出SOA已經(jīng)有點(diǎn)無(wú)人問(wèn)津的凄涼了衩匣。
下面我要簡(jiǎn)單介紹下SOA蕾总,SOA的定義:
SOA是一個(gè)軟件架構(gòu),它包含四個(gè)關(guān)鍵概念:應(yīng)用程序前端琅捏、服務(wù)生百、服務(wù)庫(kù)和服務(wù)總線。一個(gè)服務(wù)包含一個(gè)合約柄延、一個(gè)或多個(gè)接口以及一個(gè)實(shí)現(xiàn)蚀浆。
應(yīng)用程序前端可以理解為我上面所講述的調(diào)用者和前端系統(tǒng),服務(wù)庫(kù)可以理解為服務(wù)集群搜吧,這里還有個(gè)服務(wù)是什么呢市俊?
服務(wù)就是調(diào)用者和服務(wù)提供者完成某一個(gè)特定業(yè)務(wù)的合約,換句話說(shuō)就是封裝的業(yè)務(wù)規(guī)則滤奈。
打個(gè)比方摆昧,我們?cè)谔詫毴ベ?gòu)物,下訂單蜒程,付款绅你,查物流,確定付款這些操作在服務(wù)端都有獨(dú)立的服務(wù)提供搞糕,但是從購(gòu)物這個(gè)概念去理解勇吊,這些獨(dú)立的服務(wù)才能構(gòu)成這個(gè)完整的購(gòu)物行為,如果其中有地方出了問(wèn)題窍仰,會(huì)有相應(yīng)不同的操作汉规,那么這個(gè)就絕對(duì)不是調(diào)用者簡(jiǎn)單調(diào)用服務(wù)接口的問(wèn)題,需要更高層次的業(yè)務(wù)封裝,將上面這些操作封裝為一個(gè)統(tǒng)一的服務(wù)针史,這個(gè)就是所謂的服務(wù)晶伦。
最后一個(gè)要素服務(wù)總線,這就是我們本文所談的重要主題:遠(yuǎn)程調(diào)用服務(wù)了啄枕。
這里談?wù)凷OA的目的是想起到拋磚引玉的作用婚陪,讓那些想深入研究遠(yuǎn)程調(diào)用服務(wù)的人可以從SOA的角度理解遠(yuǎn)程調(diào)用服務(wù),而那些還是不明白遠(yuǎn)程調(diào)用是何物的童鞋可以通過(guò)SOA的概念來(lái)理解遠(yuǎn)程調(diào)用服務(wù)频祝。
遠(yuǎn)程調(diào)用服務(wù)技術(shù)詳解
遠(yuǎn)程調(diào)用服務(wù)技術(shù)詳解泌参,詳解,嗚嗚~~常空,這兩個(gè)字很有壓力沽一,我怕有童鞋看了這個(gè)標(biāo)題會(huì)以為我會(huì)將整套技術(shù)實(shí)現(xiàn)方案寫到里面,這個(gè)難度太高了漓糙,寫幾萬(wàn)字估計(jì)都說(shuō)不清楚铣缠,再說(shuō)真的寫的那么細(xì)致,估計(jì)很多人都看不懂了(嘿嘿昆禽,我自己也沒(méi)有技術(shù)實(shí)現(xiàn)過(guò)哦蝗蛙,這些都是構(gòu)思,構(gòu)思哦)醉鳖,所以詳解就是詳解原理捡硅。
下面我將上篇文章的架構(gòu)圖放進(jìn)來(lái),大家再仔細(xì)看看這張圖:
傳統(tǒng)的服務(wù)調(diào)用都是服務(wù)提供者和服務(wù)調(diào)用者的直接調(diào)用辐棒,從架構(gòu)圖里我們看到這里多了一個(gè)遠(yuǎn)程調(diào)用管理組件病曾,遠(yuǎn)程調(diào)用管理組件是一個(gè)獨(dú)立的服務(wù)系統(tǒng),為了保證該系統(tǒng)的穩(wěn)定性漾根。
它也一定是一個(gè)分布式的系統(tǒng)泰涂,但是這個(gè)分布式系統(tǒng)和Web的分布式系統(tǒng)是完全不同的分布式系統(tǒng),傳統(tǒng)Web應(yīng)用集群是基于HTTP協(xié)議的無(wú)狀態(tài)的特點(diǎn)設(shè)計(jì)的辐怕。
因?yàn)槊總€(gè)HTTP請(qǐng)求都是一個(gè)獨(dú)立的事務(wù)逼蒙,不同請(qǐng)求之間是沒(méi)有任何關(guān)系的,所以我們可以將Web應(yīng)用部署到不同服務(wù)器上寄疏,請(qǐng)求不管到了那臺(tái)服務(wù)器是牢,都能正常的給用戶提供相應(yīng)的服務(wù),但是Web應(yīng)用的session機(jī)制是有狀態(tài)的陕截,所以傳統(tǒng)Web集群都是要有session同步的操作驳棱,大型網(wǎng)站往往會(huì)把session功能抽象為獨(dú)立的緩存系統(tǒng)。
但是這里的遠(yuǎn)程調(diào)用管理組件的集群原理农曲,或者說(shuō)分布式原理是有別于Web應(yīng)用集群分布式原理的社搅,遠(yuǎn)程調(diào)用管理組件可以當(dāng)做一個(gè)注冊(cè)中心驻债,它會(huì)記錄下服務(wù)提供者和服務(wù)調(diào)用者的相關(guān)信息,并將這些信息推送給服務(wù)提供者或者服務(wù)調(diào)用者形葬,為了保證系統(tǒng)的執(zhí)行效率合呐,這些注冊(cè)信息都是記錄在內(nèi)存里。
我們?cè)囅胂麦弦裕绻@些注冊(cè)信息丟失淌实,整個(gè)系統(tǒng)將會(huì)不可用,因此遠(yuǎn)程調(diào)用管理組件的集群是一種保證數(shù)據(jù)可靠性和服務(wù)提供健壯性的集群猖腕,而不是建立在HTTP無(wú)狀態(tài)特性基礎(chǔ)上的集群拆祈。
我們這里假想下遠(yuǎn)程調(diào)用服務(wù)的集群運(yùn)行場(chǎng)景,我們假如有5臺(tái)服務(wù)器作為遠(yuǎn)程調(diào)用服務(wù)運(yùn)行的服務(wù)器倘感,那么每臺(tái)服務(wù)器都必須有注冊(cè)信息的冗余備份缘屹,當(dāng)服務(wù)運(yùn)行時(shí)候其中一臺(tái)服務(wù)器發(fā)生了故障,這臺(tái)故障的服務(wù)器上的數(shù)據(jù)不會(huì)丟失侠仇,此外集群應(yīng)該還要有一個(gè)檢查故障的機(jī)制,當(dāng)發(fā)現(xiàn)有臺(tái)服務(wù)器不可用的時(shí)候犁珠,能及時(shí)剔除該服務(wù)器逻炊,而zookeeper就是解決這種問(wèn)題的技術(shù)框架。
此外除了保證系統(tǒng)的穩(wěn)定性和可用性外犁享,集群的數(shù)據(jù)存儲(chǔ)方式也是很重要的余素,前面我講到集群的數(shù)據(jù)存儲(chǔ)要有一個(gè)冗余機(jī)制,除了冗余機(jī)制還要有一個(gè)很適合快速訪問(wèn)和讀寫的數(shù)據(jù)模型炊昆,而zookeeper正好包含這種數(shù)據(jù)模型桨吊,所以我設(shè)計(jì)的遠(yuǎn)程調(diào)用服務(wù)是一個(gè)很適合zookeeper應(yīng)用的場(chǎng)景。
遠(yuǎn)程調(diào)用管理組件還有一個(gè)心跳機(jī)制凤巨,心跳機(jī)制的作用是视乐,檢測(cè)服務(wù)提供者的健康性及服務(wù)提供者是否可用。
服務(wù)提供者啟動(dòng)時(shí)候會(huì)將自己的注冊(cè)信息發(fā)送給遠(yuǎn)程調(diào)用管理組件敢茁,這個(gè)注冊(cè)信息里包含服務(wù)端的ip地址和端口號(hào)佑淀,遠(yuǎn)程調(diào)用管理組件會(huì)啟動(dòng)一個(gè)線程,根據(jù)定時(shí)對(duì)這個(gè)ip地址和端口號(hào)去ping這個(gè)ip和端口號(hào)對(duì)應(yīng)的應(yīng)用是否可用彰檬。
如果不可用遠(yuǎn)程調(diào)用管理組件會(huì)反復(fù)嘗試幾次伸刃,這個(gè)次數(shù)和多久檢測(cè)心跳都是可以配置的,如果反復(fù)幾次還是不通逢倍,那么就認(rèn)定該服務(wù)不可用了捧颅。
有網(wǎng)友問(wèn)我,為什么不檢測(cè)服務(wù)調(diào)用者的心跳较雕,這個(gè)完全沒(méi)必要哦碉哑,調(diào)用者是主動(dòng)方,提供者是被動(dòng)方,這就好比你訪問(wèn)網(wǎng)站谭梗,如果你生病了不去訪問(wèn)了忘晤,系統(tǒng)沒(méi)有必要檢查你是否已經(jīng)生病了。
遠(yuǎn)程調(diào)用框架需要使用序列化和反序列化技術(shù)激捏,這點(diǎn)也讓很多童鞋不太理解设塔,不理解的原因,還是對(duì)序列化和反序列化技術(shù)的不理解远舅。
序列化技術(shù)主要是應(yīng)用于數(shù)據(jù)持久化(數(shù)據(jù)存到硬盤)或者網(wǎng)絡(luò)通訊闰蛔,不管是數(shù)據(jù)存儲(chǔ)到硬盤還是進(jìn)行網(wǎng)絡(luò)通訊,這些數(shù)據(jù)都會(huì)轉(zhuǎn)化為二進(jìn)制图柏,序列化就是將正在運(yùn)行的對(duì)象轉(zhuǎn)化為可以存儲(chǔ)和傳輸?shù)亩M(jìn)制數(shù)據(jù)序六。
而反序列化是可以將這些二進(jìn)制數(shù)據(jù)反向還原成原來(lái)的對(duì)象信息,還原的對(duì)象還是可以被程序操作的蚤吹,而我們?cè)O(shè)計(jì)的遠(yuǎn)程調(diào)用框架傳遞就是不同系統(tǒng)之間可以相互使用的程序代碼例诀,所以我們需要使用序列化和反序列化技術(shù)。
這里就有一個(gè)問(wèn)題裁着,例如我們傳輸一個(gè)對(duì)象繁涂,這個(gè)對(duì)象對(duì)應(yīng)的類是N多個(gè)類的繼承子類,而且這個(gè)對(duì)象里可能還會(huì)引用其他的對(duì)象例如String二驰,ArrayList等等扔罪。
那么為了讓反序列化的對(duì)象可用,序列化的時(shí)候就會(huì)將這些信息也包含在二進(jìn)制數(shù)據(jù)里桶雀,并且這些信息一起進(jìn)行網(wǎng)絡(luò)傳輸矿酵,這就導(dǎo)致數(shù)據(jù)傳輸量特別大,而jdk自帶的序列化機(jī)制會(huì)導(dǎo)致這些附帶信息更大矗积,所以有必要使用比jdk更好的序列化機(jī)制全肮,讓數(shù)據(jù)量變小,并且序列化和反序列化的效率更高棘捣。
對(duì)于服務(wù)提供者和服務(wù)調(diào)用者我會(huì)提供一個(gè)jar包倔矾,這些工程都要引入這個(gè)jar包,同時(shí)還需要一個(gè)配置文件來(lái)定義一些需要用戶定義的參數(shù)柱锹。
例如我們使用一個(gè)名字叫ycdy_config.properties配置文件哪自,里面的key值介紹如下:
- Config_center_url=ip:port;這個(gè)就是配置遠(yuǎn)程管理中心的ip地址和端口號(hào);
- Server_type=provider/consumer禁熏;配置是服務(wù)調(diào)用者還是提供者壤巷,不配置默認(rèn)是提供者;
- Provider_post=9999,這是服務(wù)提供者的端口號(hào)瞧毙,調(diào)用者可以不配置胧华,其實(shí)調(diào)用配置了也沒(méi)啥用寄症,如果提供者不配置,會(huì)有默認(rèn)值的矩动;
- Provider_session_timeout=9000有巧;服務(wù)提供者的超時(shí)時(shí)間,如果實(shí)際調(diào)用超過(guò)了這個(gè)時(shí)間悲没,那么說(shuō)明服務(wù)調(diào)用超時(shí)篮迎,適用于服務(wù)調(diào)用者,提供者無(wú)效
- Tick_time=3000;心跳時(shí)間示姿,這是遠(yuǎn)程調(diào)用中心檢測(cè)服務(wù)端心跳的間隔時(shí)間甜橱,適用于服務(wù)提供者;
- Again_time=3;當(dāng)服務(wù)提供者不通的時(shí)候栈戳,心跳反復(fù)檢測(cè)的次數(shù)岂傲,超過(guò)了次數(shù)就標(biāo)記該服務(wù)不可用;Provider_session_timeout子檀、Tick_time和Again_time三者之間是有一定關(guān)系镊掖,這個(gè)關(guān)系要實(shí)現(xiàn)這具體把控了;
- Ip_include_pattern=172\.17\.138.|192\.168\.0\..,這個(gè)適用于服務(wù)提供者褂痰,因?yàn)橐慌_(tái)服務(wù)器可能存在多個(gè)ip地址堰乔,當(dāng)遠(yuǎn)程調(diào)用服務(wù)組件接收到提供者的ip,用這個(gè)配置項(xiàng)來(lái)辨認(rèn)那個(gè)ip可用脐恩,這里采用正則表達(dá)式的方式;
- Ip_exclude_pattern=用于服務(wù)提供者侦讨,需要忽略的ip驶冒;
- Consumer_policy=random/rotate;適用于調(diào)用者韵卤,調(diào)用者向提供者請(qǐng)求的負(fù)載均衡策略骗污,我熟悉的只有兩種一種是是用隨機(jī)數(shù),一種使輪詢沈条,所以這里目前就這兩種選項(xiàng)需忿;
- Monitor_log=true/false;是否開啟監(jiān)控日志,適用于服務(wù)提供者蜡歹,任何系統(tǒng)日志是最重要的屋厘,否則沒(méi)法查生產(chǎn)問(wèn)題,其實(shí)這個(gè)配置項(xiàng)應(yīng)該可以充實(shí)點(diǎn)月而,但是我現(xiàn)在還沒(méi)想好汗洒,所以先給個(gè)提示,具體到了生產(chǎn)看如何實(shí)現(xiàn)吧父款。
大家看到了不管是作為服務(wù)提供者還是服務(wù)調(diào)用者使用的配置文件是一致的溢谤,而且一個(gè)應(yīng)用既可以配置成服務(wù)的調(diào)用者也可以配置成服務(wù)的提供者瞻凤,非常的靈活。
遠(yuǎn)程調(diào)用服務(wù)還需要一個(gè)重要的技術(shù)就是通訊技術(shù)世杀,這里的通訊技術(shù)我推薦netty阀参,netty是個(gè)非常好的選擇,講到通訊是個(gè)復(fù)雜的課題瞻坝,如果以后有空我再做詳細(xì)介紹蛛壳,通訊層的東西是封裝到服務(wù)提供者和服務(wù)調(diào)用者引入的jar包里,但是通訊的ip地址和端口號(hào)則是需要遠(yuǎn)程調(diào)用管理組件推送過(guò)來(lái)的湿镀。
那么在應(yīng)用里遠(yuǎn)程調(diào)用服務(wù)到底如何使用了炕吸?
哈哈,這時(shí)候spring就要上場(chǎng)了勉痴,我們看看服務(wù)調(diào)用者和服務(wù)提供者的spring配置赫模,如下所示:
<!-- 服務(wù)提供者配置 -->
<bean id="serverProvider" class="cn.com.sharpxiajun.RmifSpringProviderBean">
<property name="interfaceName" value="cn.com.ITest"></property><!-- 遠(yuǎn)程調(diào)用的接口 -->
<property name="target" ref="clsTest"></property><!-- clsTest實(shí)現(xiàn)ITest的實(shí)現(xiàn)類,clsTest這里是一個(gè)bean的id值 -->
</bean>
?
<!-- 服務(wù)調(diào)用者配置 -->
<bean id="clientConsumer" class="cn.com.sharpxiajun.RmifSpringConsumerBean">
<property name="interfaceName" value="cn.com.ITest"></property><!-- value就是Provider定義的target的接口實(shí)現(xiàn)類 -->
<property name="serialType" value="hessian"></property><!--序列化方式 -->
<property name="compressEnabled" value="true"></property><!-- 壓縮標(biāo)記 -->
</bean>
我們發(fā)現(xiàn)這個(gè)新配置和以前不同了蒸矛,這個(gè)配置將更加適合生成的開發(fā)瀑罗。
我們首先看看serverProvider的設(shè)計(jì),這個(gè)bean對(duì)應(yīng)的class是
cn.com.sharpxiajun.RmifSpringProviderBean雏掠,里面有個(gè)參數(shù)是一個(gè)interfaceName斩祭,即提供者對(duì)外的接口。
這里我會(huì)使用反射機(jī)制將接口注入到RmifSpringProviderBean乡话,而target則是具體的實(shí)現(xiàn)對(duì)象了摧玫,這就是業(yè)務(wù)對(duì)象,注意interfaceName一定要是接口绑青,因?yàn)檎{(diào)用者會(huì)根據(jù)接口進(jìn)行轉(zhuǎn)化诬像,如果是類的話,那么通用性就很差了闸婴。
clientConsumer的設(shè)計(jì)坏挠,這個(gè)bean所對(duì)應(yīng)的class是
cn.com.sharpxiajun.RmifSpringConsumerBean,其中interfaceName的value值對(duì)應(yīng)的就是遠(yuǎn)程定義的接口邪乍,和提供者的interfaceName保持一致降狠,當(dāng)提供者的數(shù)據(jù)傳導(dǎo)調(diào)用者后,就會(huì)根據(jù)這個(gè)雙方約定好的接口反序列化成可以操作的對(duì)象庇楞。
serialType是選擇序列化機(jī)制榜配,不寫的話就是調(diào)用jdk的序列化機(jī)制,這里附帶提下啊吕晌,外部的序列化程序也是放到j(luò)ar包里的哦芥牌,還有一個(gè)選項(xiàng)是compressEnabled作用是是否啟用傳輸報(bào)文壓縮。
當(dāng)調(diào)用者調(diào)用提供者服務(wù)時(shí)候聂使,jar包里netty程序會(huì)根據(jù)推送的信息(主要是ip壁拉,端口)和spring配置的bean結(jié)合起來(lái)就可以完成一次服務(wù)的調(diào)用谬俄。
遠(yuǎn)程調(diào)用服務(wù)技術(shù)詳解
遠(yuǎn)程調(diào)用管理組件和服務(wù)提供者之間有心跳機(jī)制檢測(cè),它的作用是檢測(cè)服務(wù)提供者是否能正常對(duì)外提供服務(wù)弃理。
我在上篇提出的檢測(cè)方式是使用ping的方式檢測(cè)ip和端口號(hào)溃论,其實(shí)具體實(shí)現(xiàn)中還可以有另外的方式。
因?yàn)榉?wù)提供者都會(huì)引入遠(yuǎn)程調(diào)用服務(wù)提供的jar包痘昌,在這個(gè)jar包里其實(shí)包含一個(gè)心跳測(cè)試接口钥勋,遠(yuǎn)程調(diào)用管理組件采用服務(wù)提供者和服務(wù)調(diào)用者同樣的通訊方式去調(diào)用這個(gè)心跳測(cè)試接口,如果該接口能調(diào)通辆苔,那么心跳測(cè)試成功算灸;
如果發(fā)現(xiàn)一次調(diào)不通那么再反復(fù)測(cè)試幾次,要是還是不通驻啤,再標(biāo)記該服務(wù)提供者的這臺(tái)服務(wù)器不可用菲驴,這種心跳檢測(cè)優(yōu)于使用ping的方式,因?yàn)樾奶鴻z測(cè)是完全模擬服務(wù)提供者和調(diào)用者的通訊場(chǎng)景骑冗,檢測(cè)的結(jié)果更加符合真實(shí)的情況赊瞬。
當(dāng)心跳機(jī)制檢測(cè)出了服務(wù)提供者有些服務(wù)器出現(xiàn)了故障,我們應(yīng)該還需要有一套機(jī)制贼涩,及時(shí)通知運(yùn)維人員或者相應(yīng)的開發(fā)人員巧涧,做到故障的及時(shí)處理,所以遠(yuǎn)程調(diào)用框架里應(yīng)該還要包含一個(gè)監(jiān)控系統(tǒng)健康性的監(jiān)控模塊遥倦,如果你的公司有專門的監(jiān)控系統(tǒng)那就更好了准脂。
遠(yuǎn)程調(diào)用管理組件和服務(wù)調(diào)用者還有一個(gè)推送信息的關(guān)系缓熟,這里我再描述下這個(gè)推送的關(guān)系弄捕。
當(dāng)服務(wù)提供者啟動(dòng)的時(shí)候會(huì)發(fā)送自己的ip地址和端口號(hào)豆励,遠(yuǎn)程調(diào)用管理組件接收到這些信息然后把這個(gè)ip和端口號(hào)推送到服務(wù)調(diào)用者,其實(shí)這個(gè)描述缺乏細(xì)節(jié)统诺,經(jīng)不起推敲,做個(gè)Web開發(fā)的童鞋都知道想訪問(wèn)一個(gè)應(yīng)用除了ip地址和端口號(hào)疑俭,還需要應(yīng)用的名稱粮呢,我的配置文件里只推送ip和端口號(hào),沒(méi)有應(yīng)用標(biāo)記確定是哪個(gè)應(yīng)用钞艇,那么調(diào)用者如何確定自己到底是調(diào)用了那個(gè)應(yīng)用服務(wù)了啄寡?
對(duì)于服務(wù)提供者真的不需要應(yīng)用名稱,只需要提供ip地址和端口號(hào)就行了哩照,因?yàn)椴还苣闶悄欠N服務(wù)挺物,對(duì)于調(diào)用者而言看到的都是遠(yuǎn)程調(diào)用的服務(wù)名稱,所以遠(yuǎn)程調(diào)用管理組件只需要向服務(wù)調(diào)用者推送ip地址和端口號(hào)飘弧,而服務(wù)名稱就是遠(yuǎn)程調(diào)用服務(wù)的名稱识藤,服務(wù)調(diào)用者到底調(diào)用哪個(gè)服務(wù)砚著,就是spring配置里的接口,這個(gè)接口就是具體服務(wù)的身份證了痴昧。
還有個(gè)細(xì)節(jié)我沒(méi)有講清楚稽穆,遠(yuǎn)程調(diào)用管理組件怎么知道服務(wù)調(diào)用者需要調(diào)用那些服務(wù)呢?
這里我要為遠(yuǎn)程調(diào)用管理組件開發(fā)一套管理它的Web應(yīng)用赶撰,并且在上篇的配置文件里加上一個(gè)標(biāo)記服務(wù)類型的服務(wù)標(biāo)記舌镶,該標(biāo)記只適合于服務(wù)提供者,在服務(wù)提供者啟動(dòng)的時(shí)候一起推送到遠(yuǎn)程調(diào)用管理組件里豪娜,而Web應(yīng)用一個(gè)重要的功能餐胀,就是根據(jù)服務(wù)調(diào)用者的ip地址和這些標(biāo)記建立對(duì)照關(guān)系,那么遠(yuǎn)程調(diào)用管理組件就可以知道服務(wù)調(diào)用者需要調(diào)用那些服務(wù)了瘤载。
好了否灾,服務(wù)調(diào)用者和服務(wù)提供者的關(guān)系建立好了,那遠(yuǎn)程調(diào)用管理組件是如何推送服務(wù)信息到服務(wù)調(diào)用者的呢惕虑?
我們發(fā)現(xiàn)遠(yuǎn)程調(diào)用管理組件和服務(wù)調(diào)用者之間關(guān)系是一個(gè)典型的發(fā)布-訂閱的關(guān)系坟冲,發(fā)布-訂閱的模式在設(shè)計(jì)模式里有一套解決方案:觀察者模式,這里我先簡(jiǎn)單介紹下觀察者模式:
觀察者模式定義了一種一對(duì)多的依賴關(guān)系溃蔫,讓多個(gè)觀察者對(duì)象同時(shí)監(jiān)聽(tīng)某一個(gè)主題對(duì)象健提,這個(gè)主題對(duì)象的狀態(tài)發(fā)生變化的時(shí)候會(huì)通知所有觀察者對(duì)象,使得它們能夠自動(dòng)更新自己伟叛。
通過(guò)觀察者模式的定義私痹,我們發(fā)現(xiàn)遠(yuǎn)程調(diào)用管理組件即是主題對(duì)象,服務(wù)調(diào)用者則是觀察者统刮,其實(shí)程序里信息推送的模式都是使用觀察者模式來(lái)實(shí)現(xiàn)的紊遵。
在上篇里我給大伙展示服務(wù)提供者和服務(wù)調(diào)用者的spring配置文件,接著告訴大家提供者和調(diào)用者就是使用RmifSpringProviderBean和RmifSpringConsumerBean這兩個(gè)bean就能完成相互的通訊侥蒙,我開始以為自己已經(jīng)講的很清楚了暗膜,有代碼有真相,但是結(jié)果是馬上有童鞋跟我私聊鞭衩,問(wèn)道這到底是怎么做到的呢学搜?事后我再想想,如果這個(gè)問(wèn)題不解釋細(xì)點(diǎn)還真是有很多人不明白论衍。
這里我使用的是代理模式瑞佩,下面是對(duì)代理模式的簡(jiǎn)單介紹:
代理模式及Proxy,是為其他對(duì)象提供一種代理控制對(duì)這個(gè)對(duì)象的訪問(wèn)坯台。在某些情況下炬丸,一個(gè)對(duì)象不適合或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介作用蜒蕾。
遠(yuǎn)程調(diào)用服務(wù)的一個(gè)核心設(shè)計(jì)就是要保證服務(wù)提供者和服務(wù)調(diào)用者之間的調(diào)用規(guī)則要一致稠炬,但是具體到業(yè)務(wù)的處理又能多種多樣焕阿,這個(gè)場(chǎng)景就是一個(gè)典型的代理模式。
在遠(yuǎn)程調(diào)用服務(wù)里的代理模式不是一個(gè)普通的代理模式酸纲,因?yàn)檫@種代理關(guān)系的建立都是在程序運(yùn)行中進(jìn)行的捣鲸,所以我們必須選擇使用反射機(jī)制實(shí)現(xiàn)的動(dòng)態(tài)代理模式,讀完上面我引用的文章闽坡,大家發(fā)現(xiàn)了吧栽惶,我在spring里使用的是interface方式,這說(shuō)明我的方案是使用jdk自帶的代理模式疾嗅,不過(guò)使用cglib的動(dòng)態(tài)代理外厂,用實(shí)現(xiàn)類來(lái)實(shí)現(xiàn)代理我感覺(jué)可能程序設(shè)計(jì)會(huì)更加靈活些。
遠(yuǎn)程調(diào)用服務(wù)的框架開發(fā)里代承,還有兩個(gè)重要的技術(shù):線程和通訊汁蝶,這兩個(gè)技術(shù)是遠(yuǎn)程調(diào)用框架的核心技術(shù)也是難點(diǎn)技術(shù),因?yàn)榫€程和通訊都比較復(fù)雜论悴,所以本文不展開它們具體的實(shí)現(xiàn)方式掖棉,而是談?wù)勊鼈冊(cè)谶h(yuǎn)程調(diào)用框架里的作用。
在談作用之前我要插入一點(diǎn)內(nèi)容膀估,上篇里我講到遠(yuǎn)程調(diào)用服務(wù)框架就是幾年前很火的SOA里的服務(wù)總線幔亥,如果有童鞋接觸過(guò)這種骨灰級(jí)的技術(shù),一定知道當(dāng)時(shí)的服務(wù)總線有個(gè)簡(jiǎn)稱叫ESB總線察纯。而ESB總線的通訊介質(zhì)幾乎都是WebService帕棉,當(dāng)年的SOA是源自企業(yè)級(jí)的解決方案。
而我現(xiàn)在設(shè)計(jì)的遠(yuǎn)程調(diào)用服務(wù)是針對(duì)于互聯(lián)網(wǎng)的應(yīng)用饼记,互聯(lián)網(wǎng)的遠(yuǎn)程調(diào)用框架沒(méi)有采用WebService而是使用新的通訊介質(zhì)香伴。
例如netty,或者是apache的頂級(jí)項(xiàng)目mina具则。其實(shí)當(dāng)下webservice也是一種被淘汰的技術(shù)即纲,淘汰的原因是它的效率低下,不管是傳輸?shù)臄?shù)據(jù)大小博肋,還是請(qǐng)求響應(yīng)的效率都很爛低斋。
互聯(lián)網(wǎng)的遠(yuǎn)程調(diào)用服務(wù)是一個(gè)高性能的框架,它的性能更好束昵,而且它包含了原來(lái)ESB總線的所有特點(diǎn)拔稳,由此可見(jiàn)互聯(lián)網(wǎng)的技術(shù)遠(yuǎn)遠(yuǎn)領(lǐng)先企業(yè)應(yīng)用葛峻,企業(yè)級(jí)的應(yīng)用企業(yè)相對(duì)于互聯(lián)網(wǎng)企業(yè)就是傳統(tǒng)手工業(yè)锹雏,而當(dāng)下互聯(lián)網(wǎng)的技術(shù)已經(jīng)開始引領(lǐng)企業(yè)的應(yīng)用,這就是落后就要挨打的道理术奖,沒(méi)有創(chuàng)新的意識(shí)就會(huì)被別人革命礁遵。
既然我們要設(shè)計(jì)的是高性能的遠(yuǎn)程調(diào)用服務(wù)框架轻绞,那么高性能的一個(gè)指標(biāo)就是高并發(fā),而高并發(fā)就是指你的服務(wù)到底能開啟多少個(gè)線程佣耐,所以線程寫的好壞直接關(guān)系到遠(yuǎn)程調(diào)用服務(wù)可用性的好與壞政勃。
使用線程的時(shí)候要注意以下幾個(gè)問(wèn)題:
第一,服務(wù)器的內(nèi)核一般是多核的兼砖,所以編寫線程的時(shí)候要把這些內(nèi)核都利用上去奸远,大量的線程要使用那么一定要使用上池技術(shù)。
這里我推薦的是jdk自帶的Executor框架讽挟,Executor框架設(shè)計(jì)的非常好懒叛,同時(shí)和netty的兼容性也非常不錯(cuò),最后就是線程安全的問(wèn)題耽梅,這里最難的就是線程安全薛窥,如果讓我自己實(shí)現(xiàn)線程,我對(duì)寫線程安全的信心是最不足的眼姐。
高性能的另一個(gè)指標(biāo)就是網(wǎng)絡(luò)通訊了诅迷,這里我采用的是netty框架,Netty是由JBOSS提供的一個(gè)java開源框架众旗。
Netty提供異步的罢杉、事件驅(qū)動(dòng)的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能逝钥、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序屑那。
Netty有很多優(yōu)點(diǎn),但是它最大的優(yōu)點(diǎn)是netty的長(zhǎng)連接和事件驅(qū)動(dòng)艘款,netty能幫我們屏蔽很多socket難以控制的細(xì)節(jié)持际,它的長(zhǎng)連接設(shè)計(jì)的非常不錯(cuò),減少了tcp開啟和關(guān)閉的開銷哗咆,而事件驅(qū)動(dòng)模式又大大降低了開發(fā)的難度蜘欲,但是netty本身有個(gè)缺陷,這個(gè)缺陷就是netty是一個(gè)異步的通訊框架晌柬。
但是大家看到了我們調(diào)用的場(chǎng)景都是同步姥份,因此我們必須把異步請(qǐng)求轉(zhuǎn)為同步請(qǐng)求,在前面的分布式網(wǎng)站架構(gòu)里年碘,我使用到了這種技術(shù)澈歉,哎,可惜當(dāng)時(shí)使用時(shí)候是拿來(lái)主義屿衅,異步轉(zhuǎn)同步的詳情我現(xiàn)在還不是很明了埃难,這個(gè)也是我以后需要研究研究的,這里先預(yù)留下來(lái),以后明白了再寫博客告訴大家涡尘。
好了忍弛,遠(yuǎn)程調(diào)用服務(wù)的架構(gòu)設(shè)計(jì)詳情到此結(jié)束了,下面是本文的另一個(gè)主題zookeeper了考抄。
Zookeeper技術(shù)詳解
在遠(yuǎn)程調(diào)用服務(wù)里zookeeper使用在遠(yuǎn)程調(diào)用管理組件里细疚,而服務(wù)調(diào)用者則是zookeeper的客戶端,遠(yuǎn)程調(diào)用管理組件也是遠(yuǎn)程調(diào)用服務(wù)的核心所在川梅。
如果遠(yuǎn)程調(diào)用管理組件在運(yùn)行時(shí)掛掉了疯兼,那么整個(gè)應(yīng)用也將不可用,因此遠(yuǎn)程調(diào)用管理組件必須是否可靠贫途,這種可靠性的要求甚至要高于服務(wù)提供者和服務(wù)調(diào)用者的可靠性的級(jí)別镇防,因此遠(yuǎn)程調(diào)用管理組件的設(shè)計(jì)必須是分布式的,而且一定要是可靠的分布式潮饱。
遠(yuǎn)程調(diào)用管理組件是一個(gè)完全符合zookeeper場(chǎng)景的應(yīng)用或者說(shuō)是一個(gè)標(biāo)準(zhǔn)的zookeeper應(yīng)用来氧,為了便于后面的論述,這里我的更進(jìn)一步的講解下遠(yuǎn)程調(diào)用管理組件的功能香拉。
從我前面的敘述啦扬,我們知道了遠(yuǎn)程調(diào)用管理組件核心作用是存儲(chǔ)服務(wù)提供者和服務(wù)調(diào)用者通訊的配置信息,例如存儲(chǔ)服務(wù)提供者的ip地址和端口凫碌,記錄服務(wù)提供者的服務(wù)類別扑毡,它還記錄服務(wù)調(diào)用者的ip地址和端口號(hào)(這個(gè)信息是在遠(yuǎn)程調(diào)用管理組件的Web管理系統(tǒng)里錄入的)以及服務(wù)調(diào)用者和服務(wù)提供者的對(duì)照關(guān)系。
對(duì)于服務(wù)提供者盛险,遠(yuǎn)程調(diào)用管理組件還提供心跳機(jī)制檢測(cè)服務(wù)提供者的健康狀態(tài)瞄摊,如果遠(yuǎn)程調(diào)用管理組件發(fā)現(xiàn)服務(wù)提供者一些服務(wù)器出問(wèn)題了,它會(huì)及時(shí)更新服務(wù)提供者的配置信息苦掘,并將這些變化及時(shí)推送給服務(wù)調(diào)用者换帜。
由上所述,從配置信息存儲(chǔ)的角度鹤啡,遠(yuǎn)程調(diào)用管理組件其實(shí)就是一個(gè)遠(yuǎn)程存儲(chǔ)配置信息的系統(tǒng)惯驼,而心跳機(jī)制和推送機(jī)制這是一種觀察者模式,而上面這些功能都是在分布式環(huán)境下功能递瑰,需要很高的可靠性祟牲。
本文上篇的開頭,我曾提到在hadoop技術(shù)生態(tài)圈里抖部,zookeeper曾是最讓我困惑的技術(shù)说贝,這種解困的好奇心是促使我一直很關(guān)注zookeeper技術(shù)的一個(gè)重要誘因,現(xiàn)在我有點(diǎn)理解zookeeper為何物了(不管說(shuō)深入理解慎颗,因?yàn)槊總€(gè)技術(shù)都是博大精深乡恕,永無(wú)止盡的换淆,特別是很優(yōu)秀的技術(shù))。
Zookeeper最典型的一個(gè)應(yīng)用就是可以做分布式應(yīng)用的配置服務(wù)几颜,具體點(diǎn)就是像我們平時(shí)寫的配置文件,到了分布式系統(tǒng)里也是需要一個(gè)獨(dú)立的系統(tǒng)來(lái)完成讯屈,并且是動(dòng)態(tài)的配置服務(wù)蛋哭。
既然zookeeper可以做分布式的配置服務(wù),那么我們可以通過(guò)分布式配置服務(wù)的特點(diǎn)反向的理解zookeeper的作用涮母。
我是一名java工程師谆趾,在做java的web開發(fā)的時(shí)候,會(huì)使用大量的配置文件叛本,一般這些文件是用properties屬性文件完成的沪蓬,服務(wù)啟動(dòng)時(shí)候,屬性文件里的信息會(huì)讀到內(nèi)存中来候,web系統(tǒng)從內(nèi)存中讀取這些配置信息跷叉。
這個(gè)配置信息有幾個(gè)特點(diǎn):
屬性文件一般不臺(tái)大(這里指的是系統(tǒng)運(yùn)行相關(guān)的配置文件,大伙不要把國(guó)際化的也拿過(guò)來(lái)理解坝痢)云挟,配置信息是持久化,使用時(shí)候是先加載在內(nèi)存中的转质,從內(nèi)存讀取园欣。
zookeeper也可以完成這樣的事情,而且其特點(diǎn)和傳統(tǒng)的配置文件使用幾乎一樣休蟹,zookeeper有一個(gè)文件系統(tǒng)沸枯,這個(gè)文件系統(tǒng)是用來(lái)存儲(chǔ)小文件的,我們讀取配置信息時(shí)候是在內(nèi)存里讀的赂弓,效率很高绑榴,寫信息的時(shí)候zookeeper會(huì)將配置信息持久化。
這就是為什么有的書里介紹zookeeper的性能:
Zookeeper的基準(zhǔn)吞吐量可以超過(guò)10000個(gè)操作盈魁,而對(duì)于讀操作為主的工作負(fù)載彭沼,吞吐量更是高出好幾倍。
這句話很有道理备埃,小文件寫速度很快姓惑,10000個(gè)操作木有啥問(wèn)題,都是通過(guò)內(nèi)存按脚,高好幾倍是理所當(dāng)然的于毙。
系統(tǒng)運(yùn)行的配置信息可靠性要求是很高的,既然我們現(xiàn)在使用分布式系統(tǒng)完成配置信息的讀寫操作辅搬,那么確保信息讀寫的準(zhǔn)確性是非常重要唯沮,特別是寫脖旱,要求絕對(duì)是要么成功要么失敗,這個(gè)場(chǎng)景估計(jì)很多人一看就認(rèn)為這不就是線程安全嗎介蛉?
沒(méi)錯(cuò)萌庆,是線程安全(能想到線程安全還是很牛的哦),但是大伙要看清楚啊币旧,我們現(xiàn)在是分布式系統(tǒng)践险,不同服務(wù)器之間的操作不是線程的范疇而是進(jìn)程的范疇,因此這里就需要新的保證操作安全的技術(shù)吹菱,換句話說(shuō)就是進(jìn)程安全的機(jī)制巍虫。
除此之外,分布式的配置服務(wù)之所以使用分布式就是為了保證配置服務(wù)系統(tǒng)的穩(wěn)定性和安全性鳍刷,這樣才能持續(xù)為用戶提供高質(zhì)量的服務(wù)占遥,這兩個(gè)難題看似毫不相關(guān),但是卻有一種方案同時(shí)解決這個(gè)問(wèn)題输瓜,這個(gè)方案就是zookeeper的Zab協(xié)議瓦胎。
為了說(shuō)清楚Zab協(xié)議,我們舉個(gè)例子尤揣,例如我們使用5臺(tái)服務(wù)器作為zookeeper服務(wù)器凛捏,我們向zookeeper集群發(fā)送指令,這個(gè)指令就是讀操作或者寫操作芹缔,zookeeper集群會(huì)完成下面兩個(gè)操作:
操作一:
領(lǐng)導(dǎo)者選舉坯癣,當(dāng)zookeeper啟動(dòng)的時(shí)候,這5臺(tái)服務(wù)器會(huì)選舉出一個(gè)領(lǐng)導(dǎo)者機(jī)器最欠,其他的機(jī)器則是追隨者示罗,如果有半數(shù)以上的追隨者和這個(gè)領(lǐng)導(dǎo)者通訊完畢確認(rèn)了狀態(tài),那么這個(gè)階段也就完成了芝硬。
如果領(lǐng)導(dǎo)者一直都很健康蚜点,那么領(lǐng)導(dǎo)選舉的操作就不會(huì)再促發(fā),如果領(lǐng)導(dǎo)者出問(wèn)題了拌阴,那么zookeeper就會(huì)再一次促發(fā)領(lǐng)導(dǎo)者選舉的操作绍绘。
這里有個(gè)問(wèn)題我不太確定,就是zookeeper的領(lǐng)導(dǎo)者檢測(cè)追隨者健康性迟赃,應(yīng)該也會(huì)使用心跳機(jī)制吧陪拘?如果有哪位大俠知道,可以給我評(píng)論下哦纤壁。
操作二:
如果發(fā)出的指令是寫請(qǐng)求左刽,那么所有的寫請(qǐng)求都會(huì)被轉(zhuǎn)發(fā)到領(lǐng)導(dǎo)者,再由領(lǐng)導(dǎo)者將更新的廣播發(fā)送給追隨者酌媒,當(dāng)半數(shù)以上的追隨者將修改持久化后欠痴,領(lǐng)導(dǎo)者才會(huì)提交這個(gè)更新迄靠,然后客戶端才能收到一個(gè)更新成功的響應(yīng)。這個(gè)用來(lái)達(dá)成共識(shí)的方式被設(shè)計(jì)成原子性的喇辽,這個(gè)操作要不成功要不就失敗掌挚。
由以上操作就保證了讀寫的原子性,不會(huì)發(fā)生臟數(shù)據(jù)菩咨,反復(fù)選舉領(lǐng)導(dǎo)者也保證了服務(wù)的可靠性吠式。
當(dāng)然這里還有個(gè)問(wèn)題,要是領(lǐng)導(dǎo)者出現(xiàn)故障了旦委?這時(shí)候zookeeper集群又會(huì)重復(fù)上面的領(lǐng)導(dǎo)者選舉操作。這也說(shuō)明為什么zookeeper集群要求是奇數(shù)臺(tái)的服務(wù)器雏亚,5臺(tái)服務(wù)器2臺(tái)掛了缨硝,服務(wù)仍然可以正常運(yùn)行,如果是6太服務(wù)器罢低,還是只能允許2臺(tái)服務(wù)器出故障查辩,因?yàn)槿绻?臺(tái)掛了,剩下的服務(wù)器沒(méi)有過(guò)半數(shù)网持,那么zookeeper自己都掛了宜岛,所以奇數(shù)服務(wù)器不會(huì)造成服務(wù)器資源浪費(fèi)。
對(duì)于讀操作功舀,zookeeper任意一臺(tái)服務(wù)器都可以直接給服務(wù)萍倡,附帶其他操作很少,所以高效辟汰;而寫操作列敲,只有當(dāng)所有服務(wù)器都持久化了數(shù)據(jù)后,zookeeper才會(huì)更新內(nèi)存中對(duì)應(yīng)的數(shù)據(jù)帖汞,所以會(huì)比讀操作慢多了戴而。
Zookeeper存儲(chǔ)數(shù)據(jù)操作方式和Unix文件系統(tǒng)的路徑操作一致,而內(nèi)存數(shù)據(jù)存儲(chǔ)的模型就是一個(gè)樹狀結(jié)構(gòu)了翩蘸,樹狀結(jié)構(gòu)的節(jié)點(diǎn)叫做znode所意,znode就是用來(lái)存儲(chǔ)和讀取數(shù)據(jù)的地方,這個(gè)樹的操作如下列表:
我們存儲(chǔ)的配置信息就是使用這些操作完成的催首。
例如:當(dāng)服務(wù)提供者啟動(dòng)時(shí)候?qū)⒆约旱呐渲眯畔⑼扑偷竭h(yuǎn)程調(diào)用管理組件扶踊,組件就會(huì)做創(chuàng)建節(jié)點(diǎn)或者設(shè)置znode所保存數(shù)據(jù)的操作,當(dāng)數(shù)據(jù)保存成功后郎任,zookeeper就會(huì)馬上將信息推送到服務(wù)調(diào)用者姻檀,這個(gè)推送工作zookeeper也可以完成。
zookeeper里的znode以某種形式發(fā)生了變化涝滴,每個(gè)znode上面都附帶一個(gè)觀察機(jī)制绣版,也就是我們前面說(shuō)的觀察者模式的應(yīng)用胶台,這個(gè)觀察者機(jī)制會(huì)給客戶端通知,而這個(gè)客戶端就是服務(wù)調(diào)用者杂抽。
如果心跳機(jī)制檢測(cè)到服務(wù)提供者某個(gè)服務(wù)器出故障了诈唬,zookeeper也會(huì)修改相應(yīng)的znode的信息,這時(shí)候也會(huì)促發(fā)觀察機(jī)制缩麸,通知服務(wù)調(diào)用者發(fā)生了變化铸磅。
好了,本文主題就寫完了杭朱。
Zookeeper的功能很強(qiáng)大阅仔,不僅僅包含上面我談到的運(yùn)用,本文是我深入學(xué)習(xí)zookeeper的開始弧械,有了現(xiàn)在的基礎(chǔ)八酒,再深入學(xué)習(xí)zookeeper將會(huì)容易很多。
我將面試題和答案都整理成了PDF文檔刃唐,還有一套學(xué)習(xí)資料羞迷,涵蓋Java虛擬機(jī)、spring框架画饥、Java線程衔瓮、數(shù)據(jù)結(jié)構(gòu)、設(shè)計(jì)模式等等抖甘,但不僅限于此热鞍。
關(guān)注公眾號(hào)【java圈子】獲取資料,還有優(yōu)質(zhì)文章每日送達(dá)衔彻。