会话(Session) 是ZooKeeper客户端与服务端之间的TCP长连接抽象,是维护客户端状态(如临时节点生命周期、Watcher通知、请求顺序性)的核心机制。会话通过**会话ID(sessionId)**唯一标识,由服务端在客户端连接时分配,确保分布式环境下会话的一致性。
客户端通过ZooKeeper.connect()方法发起连接时,需指定会话超时时间(sessionTimeout)(单位:毫秒)。服务端会将该值调整至2×tickTime至20×tickTime之间(tickTime是ZooKeeper的基本时间单位,默认2000ms),并生成全局唯一的sessionId(算法:高8位为服务器ID,后56位为当前时间毫秒数左移8位)。创建完成后,客户端状态转为CONNECTED,服务端通过SessionTracker(会话管理器)记录会话信息。
会话状态随连接情况动态变化,主要包括:
connect())。状态转换逻辑:CONNECTING→CONNECTED→(断开)→RECONNECTING→CONNECTED(重连成功)或CLOSED(重连失败/超时)。
服务端为提升会话超时检查效率,将所有会话按**过期时间(ExpirationTime)**分组到不同“桶”中。ExpirationTime计算公式为:
ExpirationTime = 当前时间 + sessionTimeout
服务端将ExpirationTime向上取整为tickTime的整数倍(如tickTime=2000ms,sessionTimeout=5000ms,则ExpirationTime=6000ms),并将会话放入对应桶中。检查时仅需遍历即将过期的桶,而非所有会话,大幅降低时间复杂度。
心跳是维持会话活跃的关键。客户端通过两种方式发送心跳:
sessionTimeout/3时间间隔)自动发送,触发服务端更新会话过期时间。服务端收到心跳后,调用touchSession方法更新会话的ExpirationTime,并将会话从旧桶迁移至新桶(对应新的过期时间)。
若服务端在sessionTimeout时间内未收到客户端心跳,会判定会话过期,执行以下流程:
isClosing属性设为true,停止处理该会话的新请求。ephemeralOwner不为0的节点)。SessionTracker中移除会话记录,关闭对应的NIOServerCnxn连接。此时,客户端若仍在尝试操作,会收到SessionExpired异常,需重新创建会话并恢复临时数据(如重新创建临时节点)。
客户端与服务端断开连接后,会自动启动重连机制(Reconnecting状态):
sessionTimeout内重连成功,客户端状态转为CONNECTED,可使用原sessionId和sessionPassword恢复会话(服务端验证通过后,保持会话连续性)。sessionTimeout仍未重连成功,会话被服务端清理,客户端需重新创建会话(sessionId和sessionPassword失效)。ephemeralOwner字段标识所属会话)。