1、會話概述
在ZooKeeper中,客戶端和服務端建立連接后,會話隨之建立,生成一個全局唯一的會話ID(Session ID)。服務器和客戶端之間維持的是一個長連接,在SESSION_TIMEOUT時間內,服務器會確定客戶端是否正常連接(客戶端會定時向服務器發送heart_beat,服務器重置下次SESSION_TIMEOUT時間)。因此,在正常情況下,Session一直有效,並且ZK集群所有機器上都保存這個Session信息。在出現網絡或其它問題情況下(例如客戶端所連接的那台ZK機器掛了,或是其它原因的網絡閃斷),客戶端與當前連接的那台服務器之間連接斷了,這個時候客戶端會主動在地址列表(實例化ZK對象的時候傳入構造方法的那個參數connectString)中選擇新的地址進行連接。
2、連接斷開
好了,上面基本就是服務器與客戶端之間維持會話的過程了。在這個過程中,用戶可能會看到兩類異常CONNECTIONLOSS(連接斷開)和SESSIONEXPIRED(Session過期)。連接斷開(CONNECTIONLOSS)一般發生在網絡的閃斷或是客戶端所連接的服務器掛機的時候,這種情況下,ZooKeeper客戶端自己會首先感知到這個異常,具體邏輯是在如下方法中觸發的:一種場景是Server服務器掛了,這個時候,ZK客戶端首選會捕獲異常
所以,現在對於“連接斷開”這個過程就一目了然了,核心流程如下: ZK客戶端捕獲“連接斷開”異常 ——> 獲取一個新的ZK地址 ——> 嘗試連接
在這個流程中,我們可以發現,整個過程不需要開發者額外的程序介入,都是ZK客戶端自己會進行的,並且,使用的會話ID都是同一個,所以結論就是:發生CONNECTIONLOSS的情況,應用不需要做什么事情,等待ZK客戶端建立新的連接即可。
3、會話超時
SESSIONEXPIRED發生在上面藍色文字部分,這個通常是ZK客戶端與服務器的連接斷了,試圖連接上新的ZK機器,但是這個過程如果耗時過長,超過了SESSION_TIMEOUT 后還沒有成功連接上服務器,那么服務器認為這個Session已經結束了(服務器無法確認是因為其它異常原因還是客戶端主動結束會話),由於在ZK中,很多數據和狀態都是和會話綁定的,一旦會話失效,那么ZK就開始清除和這個會話有關的信息,包括這個會話創建的臨時節點和注冊的所有Watcher。在這之后,由於網絡恢復后,客戶端可能會重新連接上服務器,但是很不幸,服務器會告訴客戶端一個異常:SESSIONEXPIRED(會話過期)。此時客戶端的狀態變成 CLOSED狀態,應用要做的事情就是的看自己應用的復雜程序了,要重新實例zookeeper對象,然后重新操作所有臨時數據(包括臨時節點和注冊Watcher),總之,會話超時在ZK使用過程中是真實存在的。
所以這里也簡單總結下,一旦發生會話超時,那么存儲在ZK上的所有臨時數據與注冊的訂閱者都會被移除,此時需要重新創建一個ZooKeeper客戶端實例,需要自己編碼做一些額外的處理。
4、會話時間(Session Time)
在《ZooKeeper API 使用》一文中已經提到,在實例化一個ZK客戶端的時候,需要設置一個會話的超時時間。這里需要注意的一點是,客戶端並不是可以隨意設置這個會話超時時間,在ZK服務器端對會話超時時間是有限制的,主要是minSessionTimeout和maxSessionTimeout這兩個參數設置的。(詳細查看這個文章《ZooKeeper管理員指南》)Session超時時間限制,如果客戶端設置的超時時間不在這個范圍,那么會被強制設置為最大或最小時間。 默認的Session超時時間是在2 * tickTime ~ 20 * tickTime。所以,如果應用對於這個會話超時時間有特殊的需求的話,一定要和ZK管理員溝通好,確認好服務端是否設置了對會話時間的限制。
轉載自:http://blog.csdn.net/kobejayandy/article/details/26289273