天天看點

Tcpdump抓包驗證zookeeper的心跳機制

一、背景

在分布式系統中,zookeeper可以作為服務注冊中心,所有提供服務的節點都可以在zookeeper上面注冊,并作為一個node被組織起來,如下圖:

Tcpdump抓包驗證zookeeper的心跳機制

在RPC架構中,這些服務提供者就是RPC服務的提供者。zookeeper注冊中心為每個服務都維持了會話session。為了監測這些服務是否線上,還使用了心跳機制。

對于zookeeper來說,這些RPC服務的提供者就是zookeeper用戶端。

網上很多人說zookeeper的配置檔案裡的第一個參數

ticktime

就是指的心跳間隔,如下圖,

ticktime = 2000

,即2000毫秒。但實際上,通過tcpdump抓包分析和源碼閱讀,可以看到其實并不是這樣的。

Tcpdump抓包驗證zookeeper的心跳機制

二、抓包

zk的服務端和用戶端之間是用ping消息來作為心跳消息的。ping是應用層協定,下層直接就是網絡層協定ICMP,(ICMP利用的是IP協定傳輸消息,很有趣,網絡層依賴網絡層),沒有使用TCP或UDP,也就是說,ZK用戶端和伺服器即使在TCP三向交握或揮手過程出現了問題,也不影響心跳消息的收發。

在RPC項目中,RPC服務提供者就是zk的用戶端,是以我們首先運作RPC服務提供者程式。

然後

ifconfig

檢視網絡配置,因為都在本地運作,是以ip位址為回環位址127.0.0.1,網卡名為lo。

然後使用linux提供的抓包工具tcpdump,運作

sudo tcpdump -i lo port 2181

(-i後接參數,lo是本地網卡名;port後的2181是zk伺服器的端口号)

抓包結果如下:

Tcpdump抓包驗證zookeeper的心跳機制

可以看到,ping消息的時間是14:31:19、14:31:29、14:31:39、14:31:49、14:31:59、

也就是間隔10秒發送一次ping消息。

而我們在zookeeper用戶端程式初始化zookeeper句柄時,調用函數zookeeper_init()傳入的會話逾時時間參數是30000,即30秒(這個也是zk預設的會話逾時時間),也就是說,zk發送心跳消息的預設時間間隔是預設會話逾時時間的1/3,即

10000ms

其實檢視zk的用戶端發送ping請求的源碼class SendThread也能找到發送ping的時間間隔,部分代碼如下:

class SendThread extends ZooKeeperThread{
......
public void run(){
	......
	final int MAX_SEND_PING_INTERVAL = 10000;
	......
	}
}
           

對于前面說的配置檔案裡的

ticktime

,是這樣解釋的:

Client端的ping心跳檢測間隔時間是輪詢隔一段時間後向Server端發送ping請求,而Server端的tickTime間隔時間作用是每隔一段時間就判斷在Server端的Client連接配接對象是否已經死亡,如果已經過期死亡則将連接配接對象進行清除關閉。是以ping心跳檢測的意義是Client端告訴伺服器我還活着,tickTime意義是定期清除沒有告訴Server端還存活的連接配接。

本文參考以下部落格:

zookeeper心跳機制源碼分析

zookeeper簡介