Zookeeper 作為一個分布式的服務(wù)框架,主要用來解決分布式集群中應(yīng)用系統(tǒng)的一致性問題,它能提供基于類似于文件系統(tǒng)的目錄節(jié)點樹方式的數(shù)據(jù)存儲吩蔑,但是 Zookeeper 并不是用來專門存儲數(shù)據(jù)的卒蘸,它的作用主要是用來維護和監(jiān)控你存儲的數(shù)據(jù)的狀態(tài)變化。通過監(jiān)控這些數(shù)據(jù)狀態(tài)的變化杯聚,從而可以達到基于數(shù)據(jù)的集群管理臼婆。
ZooKeeper官方支持Java和C語言,ZooKeeper社區(qū)為其他語言(.NET,python等)提供非官方API幌绍。使用ZooKeeper API颁褂, 應(yīng)用程序可以進行連接、CRUD操作傀广、監(jiān)聽事件颁独、設(shè)置權(quán)限等交互操作。這里以java為例伪冰。
簡介
ZooKeeper類是ZooKeeper客戶端的主類誓酒。使用ZooKeeper服務(wù),程序必須實例化一個ZooKeeper對象贮聂。所有后續(xù)的操作都是調(diào)用ZooKeeper的方法靠柑。使用最簡單的構(gòu)造方法實例化一個ZooKeeper對象, ZooKeeper(String connectString, int sessionTimeout, Watcher watcher)吓懈,所需要的參數(shù)有歼冰,連接url 、會話過期時間骄瓣、默認初始監(jiān)聽器停巷。
一旦與服務(wù)器建立了連接,會話ID就被分配給客戶端榕栏∨锨冢客戶端將定期向服務(wù)器發(fā)送心跳,以保持會話有效扒磁。只要會話有效期間庆揪,客戶端可以使用ZooKeeper 中的方法。
由于某些原因妨托,客戶端很長一段時間沒有發(fā)送心跳到服務(wù)器缸榛,超過了sessionTimeout的值,ZooKeeper服務(wù)器會認為會話過期兰伤,會話ID將變?yōu)闊o效的ID内颗。同時,客戶端ZooKeeper對象將不再可用敦腔。為了調(diào)用ZooKeeper API方法均澳,應(yīng)用程序必須創(chuàng)建一個新的客戶端ZooKeeper對象。
如果客戶端連接到當前ZooKeeper服務(wù)器失敗或沒有響應(yīng),那么客戶端會在會話ID失效前嘗試連接到另一臺服務(wù)器找前,如果連接成功糟袁,應(yīng)用程序可以繼續(xù)使用客戶端ZooKeeper對象。
ZooKeeper API的方法既有異步調(diào)用也可以同步調(diào)用躺盛,這是因為java的方法重載项戴,使用同名方法時玉掸,傳入不同的參數(shù)類型或參數(shù)個數(shù)登澜,就可以切換異步和同步調(diào)用白筹。同步方法阻塞線程直到服務(wù)器作出響應(yīng)宰啦。異步方法是排隊請求并立即結(jié)束,執(zhí)行其他語句微峰。異步方法提供了一個回調(diào)對象疲酌,該對象在成功請求后執(zhí)行皇忿,或是在返回錯誤時使用適當?shù)姆祷卮a提示錯誤锄蹂。
一些成功調(diào)用的ZooKeeper API方法可以在ZooKeeper服務(wù)器的數(shù)據(jù)節(jié)點上留下監(jiān)聽器。其他成功調(diào)用的ZooKeeper API方法可以出發(fā)這些監(jiān)聽器水慨。一旦一個監(jiān)聽器被觸發(fā)得糜,一個事件會被傳遞到第一個留下監(jiān)聽器的客戶端。每個監(jiān)聽器只能被觸發(fā)一次晰洒。因此朝抖,每個留下的監(jiān)聽器只能讓客戶端接收最多一個事件。
一個客戶端需要一個Watcher接口的實現(xiàn)類來處理傳遞給客戶端的事件谍珊。當一個客戶端斷開了當前連接并重新連接到ZooKeeper server時治宣,所有已存在的監(jiān)聽器被認為已觸發(fā),但事件因未送達客戶端而丟失了砌滞。為了確保這一點侮邀,客戶端生成一個特殊的事件告訴事件處理器一個連接已被刪除。這個特殊事件的類型是EventNone 狀態(tài)為sKeeperStateDisconnected贝润。
了解了ZooKeeper客戶端的使用以及監(jiān)聽的原理绊茧,下面看一個示例。
使用實例——實時更新server列表
場景
在分布式應(yīng)用中打掘,經(jīng)常同時啟動多個server华畏,調(diào)用方(client)選擇其中之一發(fā)起請求。
分布式應(yīng)用必須考慮高可用性和可擴展性:Server的應(yīng)用進程可能會崩潰尊蚁,或者server所在機器可能會宕機亡笑,當server不夠應(yīng)對高并發(fā)時,也可能增加server的數(shù)量横朋÷匚冢總而言之,server列表并非一成不變,而是一直處于動態(tài)的增減中绝骚。這時耐版,調(diào)用方就需要實時的更新當前在線的server列表。
思路
根據(jù)上篇文章中節(jié)點的概念压汪,和本篇的理論部分作為基礎(chǔ)粪牲,通過ZooKeeper進行功能的實現(xiàn)。具體而言止剖,在啟動server時腺阳,在ZooKeeper的某個znode(這里用/sgroup)下創(chuàng)建一個子節(jié)點,所創(chuàng)建的子節(jié)點類型為臨時穿香,這樣一來亭引,一旦server進程崩潰或宕機,與ZooKeeper連接的session就結(jié)束了皮获,那么其所創(chuàng)建的子節(jié)點會被ZooKeeper自動刪除焙蚓。當崩潰的server恢復后,或者新增Server時洒宝,同樣需要在/sgroup節(jié)點下創(chuàng)建新的子節(jié)點购公。
對于調(diào)用方(client)程序,只需要注冊/sgroup子節(jié)點的監(jiān)聽雁歌,當/sgroup下的子節(jié)點增加或減少時宏浩,ZooKeeper會通知client,此時client更新server列表靠瞎。
AppServer實現(xiàn)
AppServer的邏輯很簡單比庄,只需要在啟動時,在ZooKeeper的“/sgroup”節(jié)點下新增一個子節(jié)點即可乏盐。
將其打包待用佳窑,生成jar時需要指定入口函數(shù)。
tips:IDEA打包
選擇入口類
檢查MANIFEST.MF文件父能,Main-Class是否正確
最后可以在out目錄中找到zzz.jar文件华嘹,作為appServer的運行類文件。
至此法竞,appServer打包完畢耙厚。
AppClient實現(xiàn)
AppClient需要監(jiān)聽“/sgroup”下子節(jié)點變化事件,當事件發(fā)生時岔霸,需要得到更新的Server列表薛躬。
注冊監(jiān)聽“sgroup”下子節(jié)點的變化事件,可在getChildren方法中完成呆细。當ZooKeeper會掉監(jiān)聽器的process方法時型宝,判斷該事件是否是"/sgroup"下子節(jié)點的變化事件八匠,如果是,這調(diào)用更新server列表的邏輯趴酣,并再次注冊對該子節(jié)點變化的監(jiān)聽梨树。
由于暫時不需要拷貝部署來復用,所以直接在IDEA中運行岖寞。
運行
首先 運行ZooKeeper抡四。bin/zkServer。 啟動一個zkCli來檢查是否已存在"sgroup"節(jié)點仗谆,若不存在指巡,則創(chuàng)建。若存在隶垮,則刪除并重建此節(jié)點藻雪。
1.在IDE中運行AppClient,在控制臺會得到如下結(jié)果狸吞。
在這里實時顯示分布式環(huán)境下勉耀,所有AppServer的在線情況,此列表會實時更新蹋偏。
2.開啟多個命令行窗口瑰排,每個窗口運行AppServer。這里由于我打包名稱打成了zzz.jar暖侨,所以執(zhí)行zzz.jar。
java -jar zzz.jar server1 崇渗。server1代表server機器的主機名字逗,給每個appserver設(shè)定一個不同的主機名,觀察AppClient控制臺的輸出宅广。
AppClient控制臺會輸出這樣
依次停掉每個AppServer進程葫掉。控制臺輸出如下
本篇結(jié)束跟狱,下篇是關(guān)于ArcGIS中的zookeeper?
Too be continue......
本篇參考:http://zookeeper.apache.org/doc/r3.4.5/api/org/apache/zookeeper/ZooKeeper.html俭厚,http://coolxing.iteye.com/blog/1871520