如何进行ZooKeeper中的客户端创建连接过程分析

发布时间:2021-12-23 18:04:01 作者:柒染
来源:亿速云 阅读:130

这期内容当中小编将会给大家带来有关如何进行ZooKeeper中的客户端创建连接过程分析,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

客户端API简单使用

0.1 demo案例1

一个最简单的demo如下:

public class ZookeeperConstructorSimple implements Watcher{

    private static CountDownLatch connectedSemaphone=new CountDownLatch(1);

    public static void main(String[] args) throws IOException {
        ZooKeeper zooKeeper=new ZooKeeper("127.0.0.1:2181",5000,new ZookeeperConstructorSimple());
        System.out.println(zooKeeper.getState());
        try {
            connectedSemaphone.await();
        } catch (Exception e) {}
        System.out.println("ZooKeeper session established");
        System.out.println("sessionId="+zooKeeper.getSessionId());
        System.out.println("password="+zooKeeper.getSessionPasswd());
    }

    @Override
    public void process(WatchedEvent event) {
        System.out.println("my ZookeeperConstructorSimple watcher Receive watched event:"+event);
        if(KeeperState.SyncConnected==event.getState()){
            connectedSemaphone.countDown();
        }
    }

}

使用的maven依赖如下:

<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.4.6</version>
</dependency>

对于目前来说,ZooKeeper的服务器端代码和客户端代码还是混在一起的,估计日后能改吧。

使用的ZooKeeper的构造函数有三个参数构成

同时我们可以看到,一旦和ZooKeeper服务器连接建立成功,就会获取服务器端分配的sessionId和password,如下:

sessionId=94249128002584594
password=[B@4de3aaf6

下面就通过源码来详细说明这个建立连接的过程。

1 客户端的建立连接的过程

1.1 大体连接过程概述

首先与ZooKeeper服务器建立连接,有两层连接要建立。

建立TCP连接之后,客户端发送ConnectRequest请求,申请建立session关联,此时服务器端会为该客户端分配sessionId和密码,同时开启对该session是否超时的检测。

当在sessionTimeout时间内,即还未超时,此时TCP连接断开,服务器端仍然认为该sessionId处于存活状态。此时,客户端会选择下一个ZooKeeper服务器地址进行TCP连接建立,TCP连接建立完成后,拿着之前的sessionId和密码发送ConnectRequest请求,如果还未到该sessionId的超时时间,则表示自动重连成功,对客户端用户是透明的,一切都在背后默默执行,ZooKeeper对象是有效的。

如果重新建立TCP连接后,已经达到该sessionId的超时时间了(服务器端就会清理与该sessionId相关的数据),则返回给客户端的sessionTimeout时间为0,sessionid为0,密码为空字节数组。客户端接收到该数据后,会判断协商后的sessionTimeout时间是否小于等于0,如果小于等于0,则使用eventThread线程先发出一个KeeperState.Expired事件,通知相应的Watcher,然后结束EventThread线程的循环,开始走向结束。此时ZooKeeper对象就是无效的了,必须要重新new一个新的ZooKeeper对象,分配新的sessionId了。

1.2 ZooKeeper对象

它是面向用户的,提供一些操作API。

它又两个重要的属性:

如创建某个node操作(同步方式):

ZooKeeper对象负责创建出Request,并交给ClientCnxn来执行,ZooKeeper对象再对返回结果进行处理。

如何进行ZooKeeper中的客户端创建连接过程分析

同步方式提交一个请求后,开始循环判断该请求包的状态是否结束,即处于阻塞状态,一旦结束则继续往下走下去,返回结果。异步方式则提交一个请求后,直接返回,对结果的处理逻辑包含在回调函数中。一旦该对该请求包响应完毕,则取出回调函数执行相应的回调方法。

ZooKeeper对象主要封装用户的请求以及处理响应等操作。用户请求的执行全部交给ClientCnxn来执行,那我们就详细看下ClientCnxn的来源及大体内容。

先看看ClientCnxn是怎么来的:

如何进行ZooKeeper中的客户端创建连接过程分析

4 服务器端处理连接的过程

服务器端情况分很多种,先暂时说最简单的单机版。同时也不再给出服务器端的启动过程(后面的文章再来详细说明)。

首先介绍下服务器端的大体概况:

即判断用户传递过来的sessionTimeout时间是否在minSessionTimeout、maxSessionTimeout之间。协商完成之后,根据用户传递过来的sessionId是否是0进行不同的处理。客户端第一次请求,sessionId为0。当客户端已经连接过一个服务器地址,分配了sessionId,然后如果发生超时等异常,客户端会去拿着已经分配的sessionId去连接下一个服务器地址,此时的sessionId不为0。

sessionId为0,则代表着要创建session。sessionId不为0,则需要对该sessionId进行合法性检查,以及是否已经过期了的检查。

我们先来看看sessionId为0的情况:

![创建session](https://static.oschina.net/uploads/img/201508/01065436_4nHs.png "创建session")

大体上分三大步:1、使用sessionTracker根据sessionTimeout时间创建一个新的session 2、根据sessionId创建出密码
3、提交这个创建session的请求到请求处理器链,最终将sessionId和密码返回给客户端

下面来分别详细的说明这三个过程:

4.1 使用sessionTracker创建session

SessionTracker是用来创建删除session,执行session的过期检查的。

直接看下默认使用的SessionTrackerImpl:

如何进行ZooKeeper中的客户端创建连接过程分析

先看下session有哪些属性:

然后再来看看SessionTracker的几个数据:

要搞清楚的内容有:1 创建session的过程 2 session过期检查的过程

先来看看创建session的过程:代码很简单,就是创建一个SessionImpl对象,然后存储到SessionTracker中,同时开始计算session的超时时间。这里有一个内容就是sessionId的来历,我们可以看到就是根据nextSessionId来的,并且是不断自增的。

sessionId是一个客户端的重要标示,是全局唯一的,先来看看单机版的nextSessionId初始化:

如何进行ZooKeeper中的客户端创建连接过程分析

如何进行ZooKeeper中的客户端创建连接过程分析

单机版的服务器使用1通过计算来初始化nextSessionId。而集群版对应的id则分别是每个机器指定的sid。

综上所示保证了sessionId是唯一的,不会出现重复分配的情况。

搞清楚了sessionId的分配,接下来就要弄清楚如何进行session的过期检查问题:

我们先看下,session激活过程是怎么处理的:

如何进行ZooKeeper中的客户端创建连接过程分析

综上所述,session的激活其实就是重新计算下超时时间,最终取expirationInterval的正数倍,然后从之前时间点的集合中移除,然后再添加到新的时间点的集合中去。

至此,session的检查就方便多了,只需要在expirationInterval整数时间点上取出集合,然后一个个标记为过期即可。而那些不断被激活的session,则不断的从一个时间点的集合中换到下一个时间点的集合中。

SessionTrackerImpl也是一个线程,该线程执行内容就是session的过期检查。

4.2 根据sessionId创建出密码

回到创建session的三大步骤:

如何进行ZooKeeper中的客户端创建连接过程分析

来看下密码是如何来产生的:

Random r = new Random(sessionId ^ superSecret);
r.nextBytes(passwd);

其中superSecret为常量

static final private long superSecret = 0XB3415C00L;

使用Random的方式来随机生成字节数组。但是该字节数组,只要参数即sessionId相同,字节数组的内容就相同。即当我们知道了sessionId,就可以利用上述方式算出对应的密码,我感觉密码基本上没什么用。

再看下当客户端带着sessionId和密码进行连接的时候,这时会进行密码的检查

看了上面的代码,就再次验证了密码没什么鸟用,知道了sessionId,就完全知道了密码。所以这一块有待改进吧,应该不能由sessionId完全决定吧,如再加上当前时间等等,让客户端造不出来密码,同时服务器端存储加密后的密码。

4.2 提交这个创建session的请求到请求处理器链

本文内容已太多,这里就先简单描述下,之后再详细的讲解

如何进行ZooKeeper中的客户端创建连接过程分析

如果是成功创建session,则把sessionTimeout、sessionId、passwd传递给客户端。如果没有成功创建,上述三者的值分别是0,0,new byte[16]

之后客户端处理该响应的过程,上面已经说了,可以回头再看下。

上述就是小编为大家分享的如何进行ZooKeeper中的客户端创建连接过程分析了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注亿速云行业资讯频道。

推荐阅读:
  1. ZooKeeper客户端连接数过多
  2. zookeeper客户端功能体验

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

zookeeper

上一篇:基于netty的websocket在channelActive触发时发送数据异常问题分析是怎样的

下一篇:linux中如何删除用户组

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》