4 会话
ZooKeeper的连接与会话就是客户端通过实例化ZooKeeper对象来实现客户端与服务器创建并保持TCP连接的过程(以Java为例)
4.1 会话状态
客户端与服务端成功完成连接创建之后,就建立了一个会话
会话在其生命周期中,会在不同的会话状态之间进行切换
这些状态一般可以分为:CONNECTING、CONNECTED、RECONNECTING、RECONNECTED、CLOSE等
状态变更情况:
4.2 会话创建
3.1介绍了会话创建过程中客户端的工作流程,这里介绍服务端创建会话的过程(4.2.3)
4.2.1 Session
会话实体,代表了一个客户端会话,其包含4个基本属性:
4.2.1.1 sessionID
- 基础生成算法
参数id变量是当前ZooKeeper服务器的SID值
通过以上算法,可以获得一个单机唯一的序列号
可以概括为:高8位确定了所在机器,后56位使用当前时间的毫秒表示进行随机
- 算法细节
为什么是左移24位:
该算法存在的问题及其改进:
某些数值可能左移24位,还是会存在负数,因此算法改进一下,使用无符号右移8位(补0),这样就可以避免高位数组对SID的干扰了
4.2.2 SessionTracker
SessionTracker是ZooKeeper服务端的会话管理器,负责会话的创建、管理和清理等工作;整个会话的生命周期都离不开SessionTracker的管理;
每个会话在SessionTracker内部都保留了三份:
4.2.3 服务端创建会话的过程
分为四个步骤:
4.3 会话管理
讲解ZooKeeper服务端管理会话的方式
4.3.1 分桶策略
ZooKeeper的会话管理主要是由SessionTracker负责的,其会话管理方式为”分桶策略“:
将类似的会话放在同一区块中进行管理,以便于ZooKeeper对会话进行不同区块的隔离处理以及同一区块的统一处理:
分配的原则:每个会话的”下次超时时间点(ExpirationTime)“
ExpirationTime指会话最近一次可能超时的时间点;会话创建完毕之后,ZooKeeper就会为其计算ExpirationTime,公式如下:
ExpirationTime = CurrentTime + SessionTimeout
CurrentTime 指当前时间,单位为毫秒;SessionTimeout指会话设置的超时时间,单位为毫秒
对于时间轴上的ExpirationTime的计算:ZooKeeper的Leader服务器在运行期间会定时地进行会话超时检查,时间间隔为ExpirationInterval;所以其公式为:
保证了时间轴上的ExpirationTime为ExpirationInterval的整数倍数,方便对多个会话同时进行超时检查
例子:CurrentTime 为1370907000000,SessionTimeout为15000,ExpirationInterval为2000
优点:见4.3.3
4.3.2 会话激活
为了保持客户端会话的有效性,使用了心跳检测:
迁移会话时,将该会话从老的区块中取出,放入ExpirationTime_New对应的新区块中
实际中,会话激活会出现在以下两种情况,不单单是客户端发送PING:
4.3.3 会话超时检查
同样由SessionTracker负责,单独起一个”超时检查“线程来进行此任务
工作机制核心思路:逐个、依次地对会话桶中剩下的会话进行清理
”超时检查“线程的任务:定时检查老的区块(会话桶)
实现方式:涉及分桶策略的优点
4.4 会话清理
SessionTracker的”超时检查“线程整理出一些已经过期的会话后,就要开始进行会话清理了
步骤:
4.5 重连
当客户端和服务端之间的网络连接断开时,客户端会自动进行反复重连。直到最终成功连接上集群中的一台机器;
这种情况下,再次连接上服务端的客户端有可能会处于以下两种状态之一:
在sessionTimeout时间内,服务端会不断地检测客户端是否还处于正常连接;
如果连接断开,则用户在客户端可能会看到两类异常:CONNECTION_LOSS(连接断开)和SESSION_EXPIRED(会话过期)
接下来介绍如何处理这两类异常
4.5.1 CONNECTION_LOSS
出现的原因及其处理方式:
4.5.2 SESSION_EXPIRED
出现的原因及其处理方式:
4.5.3 会话转移:SESSION_MOVED
即4.5.1中,如果重新连接上了新的服务器并且延续了有效会话,那么就可以说会话从旧服务器转移到了新服务器上
可能出现的问题:数据覆盖
解决: