1. 程式人生 > >Zookeeper學習筆記——Zookeeper會話

Zookeeper學習筆記——Zookeeper會話

會話是Zookeeper中的重要概念之一,客戶端與服務端之間的任何互動操作都與會話相關,比如:臨時節點的生命週期、客戶請求的順序執行、Watcher通知機制等。
1、會話狀態
Zookeeper的會話狀態可分為CONNECTING、CONNECTED、RECONNECTING、RECONNECTED和CLOSE等。
開始建立Zookeeper控制代碼時,會話的狀態為CONNECTING,同時,客戶端會在伺服器地址列表中逐一選取IP地址來嘗試連線,直到成功連線上為止,此時會話狀態為CONNECTED。
如果因為網路或其他原因,客戶端與服務端之間連線斷開,則Zookeeper客戶端會自動進行重連,同時會話狀態變成CONNECTING,直到重新連線上Zookeeper之後,會話狀態才會變成CONNECTED。一般情況下,會話狀態處於CONNECTING和CONNECTED之間。
如果出現會話超時、許可權檢查失敗或客戶端主動退出等情況,那麼會話狀態會直接變成CLOSE。
Zookeeper客戶端會話狀態狀態機如圖1所示。
在這裡插入圖片描述


圖1 Zookeeper客戶端會話狀態機
2、會話建立
Session是Zookeeper的會話實體,代表客戶端會話,具有以下四個屬性:
sessionID:會話ID,唯一標識一個會話,每次會話建立時,Zookeeper都會為其分配一個全域性唯一的sessionID;
TimeOut:會話超時事件;
TickTime:下次會話超時時間點,它是一個13位的long型資料,其值接近與當前時間加上TimeOut,但不完全相等;
isClosing:標記會話是否已經被關閉,當服務端檢測到會話超時失效時,會將會話標記該屬性,確保後續不再處理該會話的請求;
(1)sessionID
sessionID為64為的長整型資料,其的生成演算法:高8位為機器標識(SID,即配置檔案myid中的值),低56位為會話生成的時間點的毫秒錶示。
3、會話管理

(1)分桶策略
SessionTracker負責Zookeeper的會話管理,其採用了分桶策略,即:將類似的會話放在同一區塊中進行管理,以便Zookeeper對會話進行不同區塊的隔離處理以及同一區塊的統一處理,如圖2所示。
在這裡插入圖片描述
圖2 Session的分桶管理策略
如圖所示,Zookeeper將所有會話分在不同的區塊中,分配的原則是會話的下次超時時間點(Expiration Time)。Expiration Time是指會話最近一次可能超時的時間點,一個新建會話的Expiration Time的計算方式如下:
Expiration Time = Current Time + Session TimeOut (單位:毫秒)
Zookeeper的Leader伺服器在執行過程中會定時檢查會話是否超時,時間間隔是Expiration Interval(單位:毫秒),預設為tickTime的值,Expiration Time的計算方法如下:
ExpirationTime = ((Current Time + Session TimeOut) / Expiration Interval + 1) * Expiration Interval
因此,圖2中的橫座標Expiration Time值總是Expiration Interval的整數倍。
(2)會話啟用

為了保持會話的有效性,客戶端會在會話超時時間到期之前向服務端傳送PING請求來保持會話的有效性(俗稱:“心跳檢測”)。同時,服務端需要不斷接受客戶端的心跳檢測,並重新啟用會話(此過程稱為Touch Session),會話啟用既能使服務端檢測到客戶端的存活性,也能讓客戶端保持連線狀態。其主要流程如圖3所示。
在這裡插入圖片描述
圖3 會話啟用流程
如圖3所示,會話啟用流程分為四步:
1.檢查會話是否已經關閉,若已關閉,則不再啟用會話;
2.計算會話新的超時時間ExpirationTime_New;
3.定位會話的當前區塊:獲取會話上次超時時間ExpirationTime_Old;
4.遷移會話:將會話從老的區塊中取出放入到ExpirationTime_New對應的區塊中。
在這裡插入圖片描述
圖4 會話遷移
在Zookeeper中,只要客戶端傳送請求到服務端就會觸發一次會話啟用,一下兩種情況都會觸發會話啟用:
1.客戶端向服務端傳送請求,包括讀寫請求;
2.如果xia客戶端發現在sessionTimeout/3時間內尚未和服務端進行任何通訊,則會主動傳送PING請求,服務端收到PING請求後,會觸發會話啟用。
(3)會話超時檢查
在Zookeeper中,SessionTracker有個單獨的執行緒(“超時檢查執行緒”)負責會話超時檢查,工作機制為:逐一堆會話桶中剩餘的會話進行清理。
如果一個會話唄啟用,則Zookeeper會將其從一個會話桶中遷移到下一個會話桶中,此時,老的會話桶中的會話都是尚未被啟用的,超時執行緒就是定時檢查這個會話桶中所有剩下的未被遷移的會話。
由於Zookeeper是以Expiration Interval的整數倍作為時間軸的,所以,超時檢查執行緒只需要在指定事件點(比如:Expiration Time1、Expiration Time2 …)上進行檢查即可。
4、會話清理
會話超時執行緒檢查出已經過期的會話後,SessionTracker就開始進行會話清理工作,大體分為以下七步:

1.標記會話狀態為“已關閉”:在會話清理期間不再處理該會話的請求;
2.發起“會話關閉”請求:Zookeeper使用提交會話關閉請求的方式使得對該會話的關閉操作在整改叢集都生效;
3.收集需要清理的臨時節點; Zookeeper的記憶體資料庫為每個會話單獨儲存了臨時節點列表。但是,在處理會話關閉請求之前,若正好有以下兩個請求到達服務端並正在處理中:
① 節點刪除請求:刪除的目標節點是臨時節點列表中的一個;
② 臨時節點建立請求:建立的目標是臨時節點列表中的一個;
對於第一個請求,需要將所有請求對應的節點路徑從臨時節點列表中移除,避免重複刪除;對於第二個請求,需要將所有這些請求對應的節點路徑新增到臨時節點列表中,以刪除這些即將被建立但是尚未儲存到記憶體資料庫中的臨時節點。
4.新增“節點刪除”事務變更:逐個為要清理的臨時節點構建“節點刪除”請求; 5.刪除臨時節點;
6.移除會話:將會話從SessionTracker中移除;
7.關閉NIOServerCnxn。

5、重連
當客戶端與服務端之間的連線斷開時,客戶端會自動嘗試重連,知道最終成功連線上。在此情況下,再次連線上伺服器的客戶端可能處於以下兩種狀態之一:
1.CONNECTED:會話超時時間內重新連線上叢集中的伺服器;
2.EXPIRED:會話超時時間之外重新連線上叢集中的伺服器,服務端已經將該會話清理,此時會話被視為非法會話。
正常情況下,客戶端會話是一直有效的,但是,當客戶端與服務端之間的連線斷開後,客戶端會看到以下兩種異常:CONNECTION_LOSS(連線斷開)和SESSION_EXPIRED(會話過期)。
(1)CONNECTION_LOSS(連線斷開)
網路閃斷或與客服端連線的伺服器出現異常導致的連線斷開,統稱為“客戶端與伺服器倆解決斷開”現象,即:CONNECTION_LOSS。
在此情況下,客戶端會自動從伺服器地址列表中重新逐個選取新的地址,並嘗試重新連線,知道最終成功連線上伺服器。
客戶端收到CONNECTION_LOSS事件候,需要等待客戶端自動完成重連,然後檢測上次操作的執行情況,比如:檢查znode是否存在以判斷是否建立成功;檢查znode資料已判斷是否更新成功。
(2)SESSION_EXPIRED(會話過期)
客戶端與服務端斷開連線後,如果重連時間超過了會話超時時間,則伺服器會進行會話清理。此時,客戶端不知道會話已經失效,狀態還是DISCONNECTED,如果客戶端重新連上了伺服器,狀態為SESSION_EXPIRED,則客戶端需要重新例項化Zookeeper物件,並且重新恢復臨時資料。
(3)SESSION_MOVED
客戶端會話從一臺伺服器轉移到另一臺伺服器,即:客戶端與服務端S1斷開連線後,重連上了服務端S2,此時會話就從S1轉移到了S2。當多個客戶端使用相同的sessionId/sessionPasswd建立會話時,會收到SessionMovedException異常。因為一旦有第二個客戶端連線上了服務端,就被認為是會話轉移了。