Zookeeper 的通信及會話
1. 前言
在前面的章節(jié)中,我們學(xué)習(xí)了 Zookeeper 的 Java 客戶端 ZkClient 和 Curator 的基本使用,那這些客戶端是如何與 Zookeeper 服務(wù)端建立通信的呢?我們就帶著這個問題開啟本節(jié)的內(nèi)容。
2. Zookeeper 的通信協(xié)議
首先我們從 Zookeeper 的通信協(xié)議開始說起。我們都知道最常用的網(wǎng)絡(luò)通信協(xié)議 TCP/IP 協(xié)議,而 Zookeeper 就是基于 TCP/IP 協(xié)議實現(xiàn)了自己的通信方式。
Zookeeper 的通信協(xié)議分為兩部分,請求協(xié)議和響應(yīng)協(xié)議,接下來我們分別進(jìn)行介紹。
2.1 請求協(xié)議
請求協(xié)議是 Zookeeper Client 向 Zookeeper Server 發(fā)送請求時所使用的協(xié)議,包含了請求頭和請求體。在 Zookeeper 中使用了 RequestHeader 類作為請求頭。
// RequestHeader 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作
public class RequestHeader implements Record{
// 客戶端序號,記錄客戶端請求發(fā)起的順序
private int xid;
// 請求類型
private int type;
}
而請求體會根據(jù)不同的請求類型來進(jìn)行封裝,接下來我們以會話創(chuàng)建、節(jié)點查詢、節(jié)點更新三種類型的請求分別介紹相對應(yīng)的請求體。
- 會話創(chuàng)建請求
當(dāng) Zookeeper 客戶端向 Zookeeper 服務(wù)端發(fā)送會話創(chuàng)建的請求時,使用 ConnectRequest 類來封裝請求體:
// ConnectRequest 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作
public class ConnectRequest implements Record {
// 請求協(xié)議的版本信息
private int protocolVersion;
// 最后一次接收到響應(yīng)的服務(wù)端 zxid
private long lastZxidSeen;
// 會話超時時間
private int timeOut;
// 會話 id
private long sessionId;
// 密碼
private byte[] passwd;
}
- 節(jié)點查詢請求
當(dāng) Zookeeper 客戶端向 Zookeeper 服務(wù)端發(fā)送節(jié)點查詢的請求時,使用 GetDataRequest 類來封裝請求體:// GetDataRequest 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作 public class GetDataRequest implements Record { // 節(jié)點全路徑 private String path; // 是否對該節(jié)點開啟監(jiān)聽 private boolean watch; }
- 節(jié)點更新請求
當(dāng) Zookeeper 客戶端向 Zookeeper 服務(wù)端發(fā)送節(jié)點更新的請求時,使用 SetDataRequest 類來封裝請求體:// SetDataRequest 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作 public class SetDataRequest implements Record { // 節(jié)點全路徑 private String path; // 節(jié)點更新的數(shù)據(jù) private byte[] data; // 節(jié)點更新后的版本,也就是在當(dāng)前版本上加 1 private int version; }
介紹了 Zookeeper 的請求協(xié)議之后,接下來我們繼續(xù)學(xué)習(xí) Zookeeper 的響應(yīng)協(xié)議。
2.2 響應(yīng)協(xié)議
響應(yīng)協(xié)議會在接收到 Zookeeper 客戶端的請求后,對請求協(xié)議進(jìn)行解析并作出響應(yīng)。和 Zookeeper 的請求協(xié)議相對應(yīng)的,Zookeeper 的響應(yīng)協(xié)議也是由響應(yīng)頭和響應(yīng)體組成,響應(yīng)體也需要根據(jù)不同的請求類型來封裝響應(yīng)體。在接收到 Zookeeper 客戶端的請求后,由 ReplyHeader 類來解析請求頭并對響應(yīng)頭進(jìn)行封裝:
// ReplyHeader 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作
public class ReplyHeader implements Record {
// 客戶端序號,記錄客戶端請求發(fā)起的順序
private int xid;
// 事務(wù)id
private long zxid;
// 錯誤狀態(tài)碼
private int err;
}
- 會話創(chuàng)建響應(yīng)
當(dāng) Zookeeper 服務(wù)端接收到 Zookeeper 客戶端的會話創(chuàng)建請求時,使用 ConnectResponse 類來封裝響應(yīng)體:// ConnectResponse 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作 public class ConnectResponse implements Record { // 請求協(xié)議的版本信息 private int protocolVersion; // 會話超時時間 private int timeOut; // 會話 id private long sessionId; // 密碼 private byte[] passwd; }
- 節(jié)點查詢響應(yīng)
當(dāng) Zookeeper 服務(wù)端接收到 Zookeeper 客戶端的節(jié)點查詢請求時,使用 GetDataResponse 類來封裝響應(yīng)體:// GetDataResponse 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作 public class GetDataResponse implements Record { // 節(jié)點的數(shù)據(jù) private byte[] data; // 節(jié)點的狀態(tài) private org.apache.zookeeper.data.Stat stat; }
- 節(jié)點更新響應(yīng)
當(dāng) Zookeeper 服務(wù)端接收到 Zookeeper 客戶端的節(jié)點更新請求時,使用 SetDataResponse 類來封裝響應(yīng)體:// SetDataResponse 類實現(xiàn)了 Record 接口來進(jìn)行序列化操作 public class SetDataResponse implements Record { // 節(jié)點的狀態(tài) private org.apache.zookeeper.data.Stat stat; }
介紹完 Zookeeper 的通信協(xié)議后,接下來我們要學(xué)習(xí)的是 Zookeeper 的會話,包括會話的結(jié)構(gòu),會話的狀態(tài)等。
3. Zookeeper 的會話
Zookeeper 是一個 C/S 架構(gòu)的服務(wù),也就是 Client — Server 的形式。在我們使用 Zookeeper 時,都是使用 Zookeeper 的客戶端向服務(wù)端發(fā)送請求,然后由服務(wù)端做出響應(yīng)返回到客戶端。在這個過程中,Zookeeper 的客戶端需要與 Zookeeper 服務(wù)端建立連接,建立一個連接就是新建一個會話,那么會話的狀態(tài)也就是 Zookeeper 客戶端與 Zookeeper 服務(wù)端的連接狀態(tài)。
接下來我們從會話的結(jié)構(gòu)開始進(jìn)行講解:
3.1 Session 的結(jié)構(gòu)
會話 Session 的結(jié)構(gòu)包括會話ID、會話超時時間、會話關(guān)閉狀態(tài) 3 個屬性:
- SessionID: 會話的唯一標(biāo)識,由 Zookeeper 自動分配。
- TimeOut: 會話從新建到被關(guān)閉的時長,這個時間由 Zookeeper 服務(wù)端來管理。
- isClosing: 會話關(guān)閉的狀態(tài),如果會話已經(jīng)被關(guān)閉,該會話就不會再被使用了。
3.2 Session 的狀態(tài)
在 Zookeeper 的運行過程中,會話 Session 會經(jīng)歷各種狀態(tài)的變化,從 Zookeeper 客戶端與 Zookeeper 服務(wù)端開始建立連接到連接被關(guān)閉,會話的狀態(tài)會經(jīng)歷以下幾種:
- CONNECTING:正在連接狀態(tài),Zookeeper 客戶端與 Zookeeper 服務(wù)端建立連接時的狀態(tài);
- CONNECTIED:已連接狀態(tài),Zookeeper 客戶端與 Zookeeper 服務(wù)端完成連接的狀態(tài);
- RECONNECTING:正在重新連接狀態(tài),當(dāng) Zookeeper 客戶端與 Zookeeper 服務(wù)端斷開連接,Session 重連策略發(fā)起重新連接時的狀態(tài);
- RECONNECTED:已經(jīng)重新連接狀態(tài),在 RECONNECTING 的基礎(chǔ)上,完成了 Zookeeper 客戶端與 Zookeeper 服務(wù)端的重新連接;
- CLOSE:連接關(guān)閉狀態(tài),Zookeeper 客戶端與 Zookeeper 服務(wù)端斷開連接的狀態(tài)。
4. 總結(jié)
在本節(jié)內(nèi)容中,我們學(xué)習(xí)了 Zookeeper 的通信協(xié)議的實現(xiàn)方式,以及 Zookeeper 會話 Session 的結(jié)構(gòu)和運行中的狀態(tài)變化。以下是本節(jié)內(nèi)容的總結(jié):
- Zookeeper 的通信協(xié)議。
- Zookeeper 的會話。