zoukankan      html  css  js  c++  java
  • ZooKeeper个人笔记Session管理

    Session

    1.sessionId  <机器的SID,当前时间>生成一个sessionId,这是全局唯一的。

    2.TimeOut 会话的超时时间,注意,这个值和客户端ZooKeeper对象指定的超时不一定相同

    3.TickTime

    4.isClosing 当SessionTracker检测到会话已经失效了,就会将这个会话的isClosing标记为true,之后这个会话将不在处理任何新的请求

    SessionTracker

    SessionTracker负责管理Session的整个会话生命周期。

    SessionTracker的创建

    如何管理多个session?

        ExpireTime1 [session,session,session]

        ExpireTime2 [session,session,session]

        新创建的Session,其expireTime=curTime+SessionTimeout

    leader服务器每隔expirationInterval时间就进行会话超时检查。

    客户端向服务器发送请求,服务器就进行一次会话激活

    客户端如果在sessionTimeout/3时间内,没有向服务器发送过任何请求,就主动发送一个PING请求,服务器收到

    该请求后激活会话。

    创建SessionTracker

    在org.apache.zookeeper.server.ZooKeeperServer的startup方法中,会创建SessionTracker,然后启动它。

        public void startup() {        
            if (sessionTracker == null) {
                createSessionTracker();
            }
    //SessionTrackerImpl继承了Thread,因此实际上他也是个线程,这里就是调用start方法执行线程。 startSessionTracker(); setupRequestProcessors(); registerJMX();
    synchronized (this) { running = true; notifyAll(); } }
        protected void createSessionTracker() {
            sessionTracker = new SessionTrackerImpl(this, zkDb.getSessionWithTimeOuts(),
                    tickTime, 1);
        }

    激活会话

     synchronized public boolean touchSession(long sessionId, int timeout) {
            if (LOG.isTraceEnabled()) {
                ZooTrace.logTraceMessage(LOG,
                                         ZooTrace.CLIENT_PING_TRACE_MASK,
                                         "SessionTrackerImpl --- Touch session: 0x"
                        + Long.toHexString(sessionId) + " with timeout " + timeout);
            }
    //获取Session SessionImpl s
    = sessionsById.get(sessionId); // Return false, if the session doesn't exists or marked as closing if (s == null || s.isClosing()) { return false; }
    //计算超时时间点
    long expireTime = roundToInterval(System.currentTimeMillis() + timeout);
    //表明没有超时
    if (s.tickTime >= expireTime) { // Nothing needs to be done return true; }
    //将Session从旧的set移动到新的set中
    //首先取出tickTime对应的set,然后从set中移除掉Session SessionSet set
    = sessionSets.get(s.tickTime); if (set != null) { set.sessions.remove(s); }
    //迁移到新的set中 s.tickTime
    = expireTime; set = sessionSets.get(s.tickTime); if (set == null) { set = new SessionSet(); sessionSets.put(expireTime, set); } set.sessions.add(s); return true; }

    会话超时检查

       @Override
        synchronized public void run() {
            try {
                while (running) {
                    currentTime = System.currentTimeMillis();
    //如果还未超时
    if (nextExpirationTime > currentTime) { this.wait(nextExpirationTime - currentTime); continue; }
    SessionSet set;
    //已经超时了,很粗暴的直接从sessionSets中移走过期的session,这里做的真是太棒了 set
    = sessionSets.remove(nextExpirationTime); if (set != null) {
    //将每一个过期的session标记为close。
    for (SessionImpl s : set.sessions) { setSessionClosing(s.sessionId);
    //注意这里哦,很重要的。这里就是调用ZooKeeperServer.expire来关闭session expirer.expire(s); } }
    //计算新的过期时间 nextExpirationTime
    += expirationInterval; } } catch (InterruptedException e) { LOG.error("Unexpected interruption", e); } LOG.info("SessionTrackerImpl exited loop!"); }
        public void expire(Session session) {
            long sessionId = session.getSessionId();
            LOG.info("Expiring session 0x" + Long.toHexString(sessionId)
                    + ", timeout of " + session.getTimeout() + "ms exceeded");
    //因为会话已经超时了,所以关闭它 close(sessionId); }
      private void close(long sessionId) {
            submitRequest(null, sessionId, OpCode.closeSession, 0, null, null);
        }

    清理会话

      找出这个session创建的所有临时节点,就是去ZooKeeper内存数据库中,根据sesionID来获取这个session创建的所有的临时节点信息,对每一个节点创建节点删除请求,从内存数据库中移除该会话的临时节点。

     将session从SessionTrackerImpl中移除

     关闭ServerCnxn。

    KeeperException.ConnectionLoseException

        客户端捕获到这种异常,只需要简单的等待org.apache.zookeeper.ZooKeeper自动重新连接上一个ZooKeeper机器即可,当重新连上了之后,客户端会受到Sync_Connected通知。

    SESSION_EXPIRED

      由于客户端在会话超时时间内没有向服务器发送PING,服务器认为会话已经过期,然后就会将其标记为失效了。如果之后客户端重新连接上了某一个机器,那么就会出现会话过期异常了。在这种情况下,只能创建一个新的ZooKeeper对象,建立一个新的会话了。

    SessionMovedException

  • 相关阅读:
    软件测试
    python学习之路
    好用的在线画图工具processon
    spring-boot集成dubbo
    公众号开放,关注软件开发过程中的哪些坑
    crontab 中curl命令无法正常执行
    近一月翻阅资料小结
    nginx+tomat8负载后,利用redis实现tomcat8的session共享
    centos7 安装nginx
    centos 上安装redis 3.0.5
  • 原文地址:https://www.cnblogs.com/francisYoung/p/5228825.html
Copyright © 2011-2022 走看看