ZooKeeper-9.7 服务器与会话- 高飞网

9.7 服务器与会话

2018-06-13 10:32:10.0

    会话(Session)是ZooKeeper的一个重要的抽象。保证请求有序、临时znode节点、监视点都与会话密切相关。因此会话的跟踪机制对ZooKeeper来说也非常重要。

    ZooKeeper服务器的一个重要任务就是跟踪并维护这些会话。在独立模式下,单个服务器会跟踪所有的会话,而在仲裁模式下,则由群首服务器来跟踪和维护。群首服务器和独立模式的服务器实际上运行相同的会话跟踪器(参考SessionTracker类和SessionTrackerImpl类)。而追随者服务器仅仅是简单地把客户端连接的会话信息转发给群首服务器(参考LeaderSessionTracker类)。

    为了保证会话的存活,服务器需要接收会话的心跳信息。心跳的形式可以是一个新的请求或者显示的ping消息(参考LearnerHandleer.run())。两种情况下,服务器通过更新会话的过期时间来触发(touch)会话活跃(参考SessionTrackerImpl.touchSession()方法)。在仲裁模式下,群首服务器发送一个PING消息给它的追随者们,追随者每半个tick就会发送一个ping消息给追随者。

    对于管理会话的过期有两个要点,一个称为过期队列(expiry queue)的数据结构(参考ExpiryQueue类),用于维护会话的过期。这个结构使用bucket来维护会话,每个bucket对应一个某时间范围内过期的会话,群首服务器每次会让一个bucket的会话过期。

    为了维护这些bucket,群首服务器会把时间分成一些片段,以expirationInterval为单位进行分割,并把每个会话分配到它的过期时间对应的bucket里,其功能就是高效地计算出一个会话的过期时间,以向上取正的方式获得具体时间间隔。

private long roundToInterval(long time) {
        // We give a one interval grace period
        return (time / expirationInterval + 1) * expirationInterval;
    }

    使用bucket的模式来管理的一个主要原因是为了减少让会话过期这项工作的系统开销。在一个ZooKeeper的部署环境中,可能其客户端就有数千个,因此也就有数千个会话。在这种场景下细粒度地检查会话过期是不合适的。如果expirationInterval短的话,那么ZooKeeper就会以这种细粒度的方式完成检查。目前expirationInterval是一个tick,通常以秒为单位。