在網絡環境很是差的狀況下,使用zookeeper集羣每每會遇到鏈接expired了:數據庫
客戶端提示鏈接從ZOO_CONNECTION_STATE變爲ZOO_EXPIRED_SEESION_STATE,而後應用失去與zookeeper集羣的鏈接。服務器
在使用過程當中,咱們通常會加大客戶端的rec_timeout值,例如設置爲30s,但對是否發生expired沒有太大影響,仔細查看文檔發現要在服務器端設置minSessionTimeout。網絡
那麼什麼狀況下鏈接會過時?session
當客戶端建立鏈接時,會隨機和一個zookeeper節點建立鏈接,並互發heartbeat;session的信息會同步到其餘zookeeper節點上,好比session的id、watcher、臨時目錄等等信息。併發
當網絡抖動或者與他建立鏈接的zk節點掉線了,這個時候client與zk的的session將斷開,此時,client無需處理,zk的重試機制會自動跟其餘存活的zk節點建立session:函數
1)若是鏈接在minSessionTimeout以內鏈接成功,那麼新的鏈接將同步以前斷開鏈接的臨時數據和watcher,並同步狀態。性能
2)若是這個重鏈接過程超過了minSessionTimeout,那麼該session就會被zk集羣提出去即expired掉,會清除該session全部資源和數據,主要包括臨時數據和watcher。當使用zookeeper_init指定session的id去從新鏈接,也會報錯,返回一個空的句柄回來。debug
下面咱們來仔細看看:server
1)通常咱們會設置鏈接超時時間,在客戶端設置,其API爲:blog
ZOOAPI zhandle_t *zookeeper_init(const char *host, watcher_fn fn, int recv_timeout, const clientid_t * clientid, void *context, int flags); 功能: 建立一個句柄(handle)和一個響應(response)這個句柄的會話(session)。 參數: host:zookeeper主機列表,用逗號間隔。 fn:用於監視的回調函數。 clientid:客戶端嘗試重連的先前會話的ID,若是不須要重連先前的會話,則設置爲 0。客戶端能夠經過調用 zoo_client_id來訪問一個已經鏈接上的而且有效的會話ID,若是clientid對應的會話超時,或者因爲某種緣由 clientid變爲無效了,那麼zookeeper_init 將返回一個非法的 zhandle_t,經過 zhandle_t 的狀態能夠獲知 zookeeper_init 調用失敗的緣由。 (一般爲 ZOO_EXPIRED_SESSION_STATE). 意思是若是該ID的鏈接是被expired了的話,從新鏈接也會失敗,服務器已經清理了相關的資源和信息。 context:暫時用不到,忽略。(TODO) flags:設置爲0,zookeeper開發團隊保留之後使用。
大量,包括代碼裏面的註釋上都沒有說recv_timeout的意思,按字面意思,確定不是session_timeout,而是多長時間zk建立鏈接不成功的時間?
2)在服務器端zoo.conf中有相關設置:minSessionTimeout,最小的客戶端超時時間,默認值爲2個ticktime,單位是毫秒:
minSessionTimeout 最小的客戶端session超時時間,默認值爲2個tickTime,單位是毫秒 maxSessionTimeout 最大的客戶端session超時時間,默認值爲20個tickTime,單位是毫秒
3)因而咱們最終修改的zoo.conf文件爲:
tickTime=1000 dataDir=/opt/zookeeper/zkdata dataLogDir=/opt/zookeeper/zklogs clientPort=2181 initLimit=5 syncLimit=2 minSessionTimeout=16000 maxSessionTimeout=30000 server.1=xxxx:2888:3888 server.2=xxxx:2888:3888 server.3=xxxx:2888:3888
注意,在僅配置了minSessionTimeout參數時,zk會啓動失敗,提示該參數超過了maxSessionTimeout值,這個時候須要在配置文件把最大值也配上。
4)服務端配置詳解:
(1)dataDir 用於存放內存數據庫快照的文件夾,同時用於集羣的myid文件也存在這個文件夾裏。 (2)dataLogDir 用於單獨設置transaction log的目錄,transaction log分離能夠避免和普通log還有快照的競爭。 (3)tickTime 心跳時間,爲了確保client-server鏈接存在的,以毫秒爲單位,最小超時時間爲兩個心跳時間。 (4)clientPort 客戶端監聽端口。 (5)globalOutstandingLimit client請求隊列的最大長度,防止內存溢出,默認值爲1000。 (6)preAllocSize 預分配的Transaction log空間block爲proAllocSize KB,默認block爲64M,通常不須要更改,除非snapshot過於頻繁。 (7)snapCount 在snapCount個snapshot後寫一次transaction log,默認值是100,000。 (8)traceFile 用於記錄請求的log,打開會影響性能,用於debug,最好不要定義。 (9)maxClientCnxns 最大併發客戶端數,用於防止DOS的,默認值是10,設置爲0是不加限制。 (11)clientPortBindAddress 能夠設置指定的client ip以及端口,不設置的話等於ANY:clientPort (12)minSessionTimeout 最小的客戶端session超時時間,默認值爲2個tickTime,單位是毫秒 (13)maxSessionTimeout 最大的客戶端session超時時間,默認值爲20個tickTime,單位是毫秒 (14)electionAlg 用於選舉的實現的參數: ①0:爲以原始的基於UDP的方式協做 ②1:爲不進行用戶驗證的基於UDP的快速選舉 ③2:爲進行用戶驗證的基於UDP的快速選舉 ④3:爲基於TCP的快速選舉,默認值爲3 (15)initLimit 多少個tickTime內,容許其餘server鏈接並初始化數據,若是zooKeeper管理的數據較大,則應相應增大這個值。 (16)syncLimit 多少個tickTime內,容許follower同步,若是follower落後太多,則會被丟棄。 (17)leaderServes leader是否接受客戶端鏈接。默認值爲yes。leader負責協調更新。當更新吞吐量遠高於讀取吞吐量時,能夠設置爲不接受客戶端鏈接,以便leader能夠專一於同步協調工做。 (18)server.x=[hostname]:nnnnn[:nnnnn] 配置集羣裏面的主機信息,其中: ①server.x:server.x的x要寫在myid文件中,決定當前機器的id, ②第一個port用於鏈接leader, ③第二個用於leader選舉。 ④若是electionAlg爲0,則不須要第二個port。 ⑤hostname也能夠填ip。 (19)group.x=nnnnn[:nnnnn] 分組信息,代表哪一個組有哪些節點,例如group.1=1:2:3 group.2=4:5:6 group.3=7:8:9。 (20)weight.x=nnnnn 權重信息,代表哪一個結點的權重是多少,例如weight.1=1 weight.2=1 weight.3=1。