架構(gòu)設(shè)計(jì):遠(yuǎn)程調(diào)用服務(wù)架構(gòu)設(shè)計(jì)及zookeeper技術(shù)詳解

?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)總圖睬罗,如下所示:

file

有了遠(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ì)看看這張圖:

file

傳統(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è)樹的操作如下列表:

file

我們存儲(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á)衔彻。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碍现,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子米奸,更是在濱河造成了極大的恐慌昼接,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悴晰,死亡現(xiàn)場(chǎng)離奇詭異慢睡,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)铡溪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門漂辐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人棕硫,你說(shuō)我怎么就攤上這事髓涯。” “怎么了哈扮?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵纬纪,是天一觀的道長(zhǎng)蚓再。 經(jīng)常有香客問(wèn)我,道長(zhǎng)包各,這世上最難降的妖魔是什么摘仅? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮问畅,結(jié)果婚禮上娃属,老公的妹妹穿的比我還像新娘。我一直安慰自己护姆,他們只是感情好矾端,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著卵皂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪渐裂。 梳的紋絲不亂的頭發(fā)上豺旬,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天钠惩,我揣著相機(jī)與錄音柒凉,去河邊找鬼。 笑死篓跛,一個(gè)胖子當(dāng)著我的面吹牛膝捞,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播愧沟,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼蔬咬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了沐寺?” 一聲冷哼從身側(cè)響起林艘,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎混坞,沒(méi)想到半個(gè)月后狐援,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡究孕,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年啥酱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厨诸。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡镶殷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出微酬,到底是詐尸還是另有隱情绘趋,我是刑警寧澤颤陶,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站埋心,受9級(jí)特大地震影響指郁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拷呆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一闲坎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茬斧,春花似錦腰懂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至娄蔼,卻和暖如春怖喻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背岁诉。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工锚沸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涕癣。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓哗蜈,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坠韩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子距潘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354