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
ZooKeeper中“对话”的那些事儿
由图1可知,此时建立的“会话”的ID为“0x1540339295d0004”。在该程序运行过程中和运行后,可以执行ZooKeeper Server的dump命令,从而可以查看该“会话”的信息。查看结果分别如图2和3所示。

图2
ZooKeeper中“对话”的那些事儿

图3
ZooKeeper中“对话”的那些事儿
由图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
ZooKeeper中“对话”的那些事儿
由图4可知,此时建立的“会话”的ID为“0x1540339295d0003”。在该程序运行过程中和运行后,可以执行ZooKeeper Server的dump命令,从而可以查看该“会话”的信息。查看结果分别如图5,6,7,8和9所示。

图5
ZooKeeper中“对话”的那些事儿

图6
ZooKeeper中“对话”的那些事儿

图7
ZooKeeper中“对话”的那些事儿

图8
ZooKeeper中“对话”的那些事儿

图9
ZooKeeper中“对话”的那些事儿
由图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没有发生变化。
ZooKeeper中“对话”的那些事儿

三、其他

“会话”的Client端会不断向它的Server端发送心跳请求,以保持“会话”的活跃,避免该“会话”的Server端在“timeout”时间内收不到任何来自Client端的数据,从而将该“会话”判定为“过期”,并将其结束。



备注:
本文是对《ZooKeeper》 Chapter 2 Getting to Grips with ZooKeeper中的“4.2、使用ZooKeeper实现一个分布式应用程序之‘会话’”所描述内容的验证和扩展。