1. 程式人生 > >ZooKeeper中“會話”的那些事兒

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端的資料,從而將該“會話”判定為“過期”,並將其結束。