ZooKeeper中“會話”的那些事兒
一、基本概念
ZooKeeper Client欲請求ZooKeeper Server的服務,首先必須與ZooKeeper Server進行連線,建立“會話”(Session)。
二、行為
2.1、結束“會話”
2.1.1、由“會話”的Client端顯式結束“會話”
舉例說明,假如現在有如下程式碼:
package com.dslztx.zookeeper;
import org.apache.zookeeper.*;
import java.io.IOException;
import java.util.Date;
public class Master {
String hostPort;
Integer sessionTimeout;
Watcher watcher;
ZooKeeper zk = null;
public Master(String hostPort, Integer sessionTimeout, Watcher watcher) {
this.hostPort = hostPort;
this.sessionTimeout = sessionTimeout;
this.watcher = watcher;
}
void startZK() throws IOException {
zk = new ZooKeeper(hostPort, sessionTimeout, watcher);
}
void stopZK() throws InterruptedException {
if (zk != null) {
zk.close();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
String hostPort = "127.0.0.1:2181" ;
Integer sessionTimeout = 600000;
Watcher watcher = new SessionWatcher();
Master m = new Master(hostPort, sessionTimeout, watcher);
m.startZK();
System.out.println("start to create session,now time:" + new Date());
// 等待兩分鐘讓session能夠完成初始化
Thread.sleep(60000 * 2);
// 顯式關閉session
System.out.println("close the session,now time:" + new Date());
m.stopZK();
// 殺死程序
System.out.println("kill process,now time:" + new Date());
System.exit(0);
}
}
class SessionWatcher implements Watcher {
public void process(WatchedEvent watchedEvent) {
System.out.println(watchedEvent);
}
}
執行後結果如圖1所示。
圖1
由圖1可知,此時建立的“會話”的ID為“0x1540339295d0004”。在該程式執行過程中和執行後,可以執行ZooKeeper Server的dump
命令,從而可以檢視該“會話”的資訊。檢視結果分別如圖2和3所示。
圖2
圖3
由圖2,圖3可知,一旦在“會話”的Client端發出結束“會話”的指令,那麼“會話”會立即被結束。
2.1.2、由“會話”的Server端基於過期認定,將“會話”結束
package com.dslztx.zookeeper;
import org.apache.zookeeper.*;
import java.io.IOException;
import java.util.Date;
public class Master {
String hostPort;
Integer sessionTimeout;
Watcher watcher;
ZooKeeper zk = null;
public Master(String hostPort, Integer sessionTimeout, Watcher watcher) {
this.hostPort = hostPort;
this.sessionTimeout = sessionTimeout;
this.watcher = watcher;
}
void startZK() throws IOException {
zk = new ZooKeeper(hostPort, sessionTimeout, watcher);
}
void stopZK() throws InterruptedException {
if (zk != null) {
zk.close();
}
}
public static void main(String[] args) throws IOException, InterruptedException {
String hostPort = "127.0.0.1:2181";
Integer sessionTimeout = 600000;
Watcher watcher = new SessionWatcher();
Master m = new Master(hostPort, sessionTimeout, watcher);
m.startZK();
System.out.println("start to create session,now time:" + new Date());
// 等待兩分鐘讓session能夠完成初始化
Thread.sleep(60000 * 2);
// 殺死程序
System.out.println("kill process,now time:" + new Date());
System.exit(0);
}
}
class SessionWatcher implements Watcher {
public void process(WatchedEvent watchedEvent) {
System.out.println(watchedEvent);
}
}
執行後結果如圖4所示。
圖4
由圖4可知,此時建立的“會話”的ID為“0x1540339295d0003”。在該程式執行過程中和執行後,可以執行ZooKeeper Server的dump
命令,從而可以檢視該“會話”的資訊。檢視結果分別如圖5,6,7,8和9所示。
圖5
圖6
圖7
圖8
圖9
由圖5,圖6,圖7,圖8和圖9可知,對於“會話”的Server端來說,只有該“會話”的Client端在“timeout”(這個“timeout”的值在這裡被取為“600000”,即10分鐘)時間內沒有傳送任何資料,該“會話”才會被判定為“過期”,該“會話”才會被結束。
2.2、重連另外一臺ZooKeeper Server,原“會話”不變
某個ZooKeeper Client與某個ZooKeeper Server進行連線,建立了“會話”,當該ZooKeeper Client與該ZooKeeper Server之間的連線斷開,該ZooKeeper Client會選中ZooKeeper Server叢集中某臺ZooKeeper Server(有可能是原來的ZooKeeper Server)進行重連,得到的“會話”是原來的“會話”,而不是新建了一個“會話”,最明顯的證據是“會話”ID沒有發生變化。
三、其他
“會話”的Client端會不斷向它的Server端傳送心跳請求,以保持“會話”的活躍,避免該“會話”的Server端在“timeout”時間內收不到任何來自Client端的資料,從而將該“會話”判定為“過期”,並將其結束。