当前位置:编程学习 > 网站相关 >>

zookeeper session tracker机制分析

说到zookeeper session管理 ,免不了要问

什么是session?

session id/session是如何产生的?

session 信息如何存储?

本文以session tracker线程【详见SessionTrackerImpl】的运行机制作为主线,并尝试解答一些相关问题

 


1)session基础

 

在介绍session tracker线程之前先回答几个问题

 


1.1) 什么是session?

 

zookeeper中session意味着一个物理连接,客户端connect成功之后,会发送一个connect型请求,此时就会有session 产生(下面会具体讲)

 


1.2)sessionid是如何产生的?

 

在SessionTrackerImpl实例化的时候就会调用下面的函数【详见SessionTrackerImpl.initializeNextSession】

123456 public static long initializeNextSession(long id) {       long nextSid = 0;       nextSid = (System.currentTimeMillis() << 24) >> 8;       nextSid =  nextSid | (id <<56);       return nextSid;   }

产生的值会存入nextSessionId属性,以后一旦有新的连接(session)产生,就会nextSessionId++

 

 

1.3)session是如何产生的?

 


接到一个连接类型的请求【详见ZooKeeperServer.processConnectRequest】

12345678910111213141516171819202122232425262728 int sessionTimeout = connReq.getTimeOut();        byte passwd[] = connReq.getPasswd();        int minSessionTimeout = getMinSessionTimeout();        if (sessionTimeout < minSessionTimeout) {            sessionTimeout = minSessionTimeout;        }        int maxSessionTimeout = getMaxSessionTimeout();        if (sessionTimeout > maxSessionTimeout) {            sessionTimeout = maxSessionTimeout;        }        cnxn.setSessionTimeout(sessionTimeout);        // We don't want to receive any packets until we are sure that the        // session is setup        cnxn.disableRecv();        long sessionId = connReq.getSessionId();        if (sessionId != 0) {            long clientSessionId = connReq.getSessionId();            LOG.info("Client attempting to renew session 0x"                    + Long.toHexString(clientSessionId)                    + " at " + cnxn.getRemoteSocketAddress());            serverCnxnFactory.closeSession(sessionId);            cnxn.setSessionId(sessionId);            reopenSession(cnxn, sessionId, passwd, sessionTimeout);        } else {            LOG.info("Client attempting to establish new session at "                    + cnxn.getRemoteSocketAddress());            createSession(cnxn, passwd, sessionTimeout);        }

 


1.3.1)确定session的timeout和id
【详见SessionTrackerImpl.createSession】

   

1234 synchronized public long createSession(int sessionTimeout) {        addSession(nextSessionId, sessionTimeout);        return nextSessionId++;    }

可见产生session需要两个元素,一个是sessionid,一个是timeout

timeout由客户端确定,但必须在服务器规定的最大的timeout(ticktime*20)和最小的timeout(ticktime*2)之间

如果客户端没有指定sessionid,那么就会产生一个新的session【详见ZooKeeperServer.createSession】,否则会reopen【详见ZooKeeperServer.reopenSession】

sessionid的产生上面解释过了

1.3.2)实例化session及相关关系存放
【详见SessionTrackerImpl.addSession】


12345678910 sessionsWithTimeout.put(id, sessionTimeout);        if (sessionsById.get(id) == null) {            SessionImpl s = new SessionImpl(id, sessionTimeout, 0);            sessionsById.put(id, s);            if (LOG.isTraceEnabled()) {                ZooTrace.logTraceMessage(LOG, ZooTrace.SESSION_TRACE_MASK,                        "SessionTrackerImpl --- Adding session 0x"                        + Long.toHexString(id) + " " + sessionTimeout);            }        }

一个重要的数据结构sessionsWithTimeout存放sessionid和timeout的映射

另一个重要的数据结构sessionsById存放sessionid和SessionImpl实例的映射

1.3.3)确定session实例的tickTime及sessionSets关系维护
【详见SessionTrackerImpl.touchSession】

 

 


12345678910111213141516 long expireTime = roundToInterval(System.currentTimeMillis() + timeout);        if (s.tickTime >= expireTime) {            // Nothing needs to be done            return true;        }        SessionSet set = sessionSets.get(s.tickTime);        if (set != null) {            set.sessions.remove(s);        }        s.tickTime = expireTime;        set = sessionSets.get(s.tickTime);        if (set == null) {            set = new SessionSet();            sessionSets.put(expireTime, set);        }        set.sessions.add(s);

 


根据当前时间和timeout计算本session 的expireTime即tickTime

一个重要的数据结构sessionSets 存放过期时间和一组session实例(相同过期时间)的映射的建立及维护

session实例的tickTime的确定

 

 

 

2)session tracker线程的机制

 


在zookeeper服务体系中,专门有一个线程(session tracker)维护session【详见SessionTrackerImpl.run】,重要代码如下

1234567891011121314 currentTime = System.currentTimeMillis();if (nextExpirationTime > currentTime) {    this.wait(nextExpirationTime - current

补充:综合编程 , 其他综合 ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,