美文网首页
Zookeeper会话管理

Zookeeper会话管理

作者: 鸿雁长飞鱼龙潜跃 | 来源:发表于2019-06-11 09:58 被阅读0次

    Zookeeper会话管理

    一,会话实体Session类

    Session是一个接口,定义在SessionTracker中。

    public interface Session{

        long getSessionId();

        int getTimeout();

        boolean isClosing();

    }

    1,sessionId

    sessionId是会话的唯一标识,客户端在创建会话时,SessionTracker会调用方法,生成一个全局唯一的sessionId。

    2,timeout

    会话超时时间,Zookeeper在创建客户端实例时,会传入一个参数sessionTimeout,这个就是会话超时时间。SessionTracker在创建会话时,会把这个超时时间发给服务端,服务端会根据这个超时时间,计算一个超时时间。

    3,isClosing

    这个属性是用来标识一个会话是否被关闭。

    如果一个会话被服务端判断为失效关闭了,那么isClosing就会置为true。有什么作用呢?作用就是对于已经标识为关闭的会话,不再处理该会话的请求。防止出现这种情况:一个会话已经关闭了,但是由于网络原因或者其他原因,这个会话的请求又来了,这时候果断拒绝该请求。

    二,会话sessionId是如何生成的

    sessionId是一个唯一标识,Zookeeper是如何生成这个唯一标识的呢?

    源码如下:

    public static long initializeNextSession(long id) {

        long nextSid = 0L;

        nextSid = System. currentTimeMillis() << 24 >>> 8;

        nextSid |= id << 56; //id值得是机器的sid

        return nextSid;

    }

    很简单的一段代码,使用的是java的位操作,详细过程这里不再赘述,感兴趣的可以在网上看一下。我们这里只关注一个点,那就是,这个sessionId由2部分构成,一个是机器号,二进制的前8位,一个是当前系统时间,二进制的后面56位。

    总得来说就是:

    sessionId = 机器号 + 系统时间

    我又想问个问题了:如果sessionId的生成算法是这样的话,那是不是意味着,集群中的服务端机器的最大数量是256,也就是2的8次方?

    三,会话管理器SessionTracker

    Zookeeper会话的核心是会话管理器SessionTracker。说到Zookeeper会话,我们就要说说分桶策略。

    分桶策略是SessionTracker管理会话的一个关键策略。什么是分桶策略呢?

    网上说法众说纷纭,看完,我懵了。好吧,我自己看源代码理解一下。

    首先,第一点,这个桶是什么呢?应该是一个set集合,也就是this.SessionSet,这个类是一个内部类,定义在SessionTracker的实现类SessionTrackerImpl中。

    什么是分桶?那意思就是有多个桶,都有哪些桶呢?

    有三个桶,如下源码定义:

    HashMap<Long, SessionTrackerImpl.SessionImpl> sessionsById = new HashMap();

    HashMap<Long, SessionTrackerImpl.SessionSet> sessionSets = new HashMap();

    ConcurrentHashMap<Long, Integer> sessionsWithTimeout = new HashMap();

    接下来,我们要看看这三个桶都是存放什么数据的?

    sessionsById:这个桶存放session的逻辑是这样的,如果新创建的session在这个桶中不存在,就会把创建的session放到这个桶里。

    sessionSets:这个桶的存放逻辑就比较复杂了。

    第一个条件:sessionsById中有记录,并且isClosing=false。

    第二个条件:tickTime小于expireTime

    第三个条件:根据tickTime在sessionSets中查询不到记录。

    综合来看,这个桶里存放的就是未超时的会话。这个桶就是分桶策略的具体实现!

    sessionsWithTimeout:这个桶存放session的逻辑是这样的,每次新创建session,就会把创建的session放到这个桶里。

    接下来我们看看分桶策略到底是如何工作的?首先我们可以发现,sessionSets这个桶是根据过期时间ExpirationTime来进行删除会话操作的。其他两个桶都是根据sessionId来进行删除的。

    根据过期时间ExpirationTime来进行删除,这里是重点,也就是说,这样可以实现批量删除多个会话的目的。这就是分桶策略。

    好,接下来我们理解一下下面这段话。

    《从Paxos到Zookeeper》一书中是这样描述的:

    所谓分桶策略,是指将类似的会话放在同一区块中进行管理,以便于ZooKeeper对会话进行不同区块的格里处理以及同一区块的统一处理。

    ZooKeeper将所有的会话都分配在了不同的区块之中,分配的原则是每个会话的“下次超时时间点”(ExpirationTime)。

    结合上面的分析,我总结一下Zookeeper会话的分桶策略。

    1,分桶是在sessionSets这个桶里进行的,其他两个桶和分桶策略没有关系。

    2,HashMap<Long, SessionTrackerImpl.SessionSet> sessionSets = new HashMap();

    sessionSets这个桶是一个HashMap,这个HashMap以过期时间为key,以SessionTrackerImpl.SessionSet集合为value的一个HashMap。

    3,SessionTrackerImpl.SessionSet这个集合是一个Set集合,里面存放的就是所有过期时间相同的session会话id。

    四,会话清理

    会话清理主要流程如下:

    1,标记会话状态为已关闭。

    字段isClosing置为true。

    2,发起会话关闭请求。

    为了使关闭操作在整个集群中生效,Zookeeper使用了提交会话关闭请求的方式,并立即交给PrepRequestProcessor处理器进行处理。

    3,收集需要清理的临时节点。

    在Zookeeper中,一旦某个会话失效后,那么和该会话关联的临时节点都需要清理。因此,需要先把这些临时节点整理出来。如何整理呢?如何找到一个会话的所有临时节点呢?

    在Zookeeper的内存数据库中,会为每个会话保存一份临时节点集合。只需要根据sessionId就可以获取到一个会话的所有临时节点。

    4,添加节点删除事务变更。

    5,删除临时节点。

    FinalRequestProcessor负责最后的删除操作。

    6,移除会话。

    会话的节点都删除以后,接下来就是删除会话。SessionTracker会把该会话从集合中清理掉。主要是这三个集合:

    sessionSets

    sessionsWithTimeout

    sessionsById

    7,关闭NIOServerCnxn。

    五,会话重连

    当客户端与服务端的网络连接断开时,Zookeeper客户端会自动反复重连,直到重新连上Zookeeper集群中的一台服务端为止。

    这里主要说一下两个点,首先客户端和服务端的连接是TCP长连接。其次服务端一旦收到客户端的心跳检测,都会重新执行会话激活的逻辑,因此在正常情况下,客户端会话是一直有效的。

    相关文章

      网友评论

          本文标题:Zookeeper会话管理

          本文链接:https://www.haomeiwen.com/subject/tqrffctx.html