ZK的会话管理机制

客户端连接zk,有zk分配一个全局唯一的sessionId,客户端需要配置超时时间timeOut并传到zk,zk会据此计算会话下一次超时的时间点,zk根据这个时间点按照分桶策略进行分开存放,zk会给session设置一个isClosing属性、如果检测到超时会将该属性标记为关闭。

图片[1]-ZK的会话管理机制-不念博客

会话状态:CONNECTINGCONNECTEDRECONNECTINGRECONNECTEDCLOSE

SessionTracker:zk中的会话管理器,负责会话的创建、管理和清理

  • sessionsWithTimeout:一个ConcurrentHashMap,用来管理会话的超时时间
  • sessionsById:HashMap,维护sessionId到session的映射
  • sessionsSets:HashMap,会话超时后进行归档,便于恢复和管理

ExpiractionTime = CurrentTime + SessionTimeout

SessionTracker根据ExpiractionTime将session进行分桶管理,同时按照一定的时间间隔进行定期检查,

同时客户端读写请求都可以将session的超时时间重置,SessionTracker会将session进行分桶迁移,如果没有读写请求,客户需要发送ping心跳链接,否则session超时会被清除

会话清理:

  • 标记isClosing为关闭,此时该会话有新的请求也无法处理
  • 发起会话关闭请求,同步到整个集群,使用提交的方式
  • 收集需要清理的临时节点,先获取内存数据库中会话对应的临时节点集合,如果此时有删除节点的请求到达,将请求对应的节点路径从集合中移除,避免重复删除,如果有创建节点请求到达、则将请求中的路径添加到集合中
  • 添加删除事务变更,将节点删除事务添加到outstandingChanges中,触发watch
  • 删除临时节点
  • 移除会话
  • 关闭连接

连接断开后客户端可以重连zk,如果该session未过期,session重新变为CONNECTED

如果时间超过sessinTimeout,服务器则会进行会话的清理工作,如果此时ZK客户端才恢复连接,则会收到State为Expired的WatchedEvent,并断开与服务器的连接。

重连:断开后更换服务器链接,RECONNECTING状态,会将会话迁移到新连接的服务器上

当一个客户端发一个心跳请求个服务端,但是网络延时,导致服务端没有收到,过一会后,客户端连接上了另一个新的服务端,在这之后,之前的心跳被旧的服务端收到了,这时候旧的服务端会被提醒,当前session已经被转移了,然后旧的服务端会关闭这个连接。客户端一般不会感知到这个异常,因为旧连接一般都会被关闭。但是还有一个特殊情况,两个客户端同时使用保存这的session id+密码来重新连接服务端,第一个连接成功,紧着第二个又连接成功,这会导致第一个连接被关闭,然后就是这两个客户端无限重连了

© 版权声明
THE END