本篇内容主要讲解“zk中的会话管理SessionTrackerImpl的方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“zk中的会话管理SessionTrackerImpl的方法”吧!
SessionTrackerImpl中包含实现SessionImpl继承Session(在SessionTracker中) SessionTracker接口
SessionImpl是session属性集合类
属性
sessionsById | sessionid和会话的对应map |
sessionExpiryQueue | 会话到期队列 |
sessionsWithTimeout | sessionid对应过期时间 |
nextSessionId | 下一个sessionid |
expirer | 让session过期,获取服务id |
running | 运行中 |
涉及到的类ExpiryQueue
类SessionImpl
类SessionExpirer
会话管理功能主要有:
1 会话过期
2 设置会话超时时间
3 生成下一个会话id
方法
将time->sessions map转成time->sessionIds 映射
getSessionExpiryMap
public synchronized Map<Long, Set<Long>> getSessionExpiryMap() { // Convert time -> sessions map to time -> session IDs map Map<Long, Set<SessionImpl>> expiryMap = sessionExpiryQueue.getExpiryMap(); Map<Long, Set<Long>> sessionExpiryMap = new TreeMap<Long, Set<Long>>(); for (Entry<Long, Set<SessionImpl>> e : expiryMap.entrySet()) { Set<Long> ids = new HashSet<Long>(); sessionExpiryMap.put(e.getKey(), ids); for (SessionImpl s : e.getValue()) { ids.add(s.sessionId); } } return sessionExpiryMap; }
run 超时会话检查线程,更新超时时间
public void run() { try { while (running) { //没有超时,需要等待超时时间 long waitTime = sessionExpiryQueue.getWaitTime(); //线程等待一段时间 if (waitTime > 0) { Thread.sleep(waitTime); continue; } //已经超时了,拿出会话队列中的会话进行清理 for (SessionImpl s : sessionExpiryQueue.poll()) { ServerMetrics.getMetrics().STALE_SESSIONS_EXPIRED.add(1); //将标记设置为SessionImpl isClosing true setSessionClosing(s.sessionId); //zookeeperServer让session过期 expirer.expire(s); } } } catch (InterruptedException e) { handleException(this.getName(), e); } LOG.info("SessionTrackerImpl exited loop!"); }
方法 | 说明 |
getSessionTimeout | 通过sessionId获取超时时间 |
setSessionClosing | 设置会话关闭 |
removeSession | 通过sessionId移除会话,同时移除会话相关的映射关系图 |
createSession(int sessionTimeout) | 创建session,指定过期时间 |
trackSession(sessionId, sessionTimeout); | 取得sessionId,调用trackSession(sessionId, sessionTimeout);方法进行session创建,更新会话超时时间
|
@Override public synchronized boolean trackSession(long id, int sessionTimeout) { boolean added = false; SessionImpl session = sessionsById.get(id); //没有就新增一个session对象 if (session == null) { session = new SessionImpl(id, sessionTimeout); } // findbugs2.0.3 complains about get after put. //?为什么 // long term strategy would be use computeIfAbsent after JDK 1.8 SessionImpl existedSession = sessionsById.putIfAbsent(id, session); if (existedSession != null) { session = existedSession; } else { added = true; if (LOG.isDebugEnabled()) { LOG.debug("Adding session 0x{}", Long.toHexString(id)); } } if (LOG.isTraceEnabled()) { String actionStr = added ? "Adding" : "Existing"; ZooTrace.logTraceMessage( LOG, ZooTrace.SESSION_TRACE_MASK, "SessionTrackerImpl --- " + actionStr + " session 0x" + Long.toHexString(id) + " " + sessionTimeout); } //存在更新超时时间 updateSessionExpiry(session, sessionTimeout); return added; }
方法 | 说明 | 涉及异常 |
commitSession(long id, int sessionTimeout) | 提交session | UnknownSessionException |
isTrackingSession(long sessionId) | 是否为可以追踪会话,说明会话有效 | SessionExpiredException |
checkSession(long sessionId, Object owner) | 通过会话和拥有者检查会话信息 | SessionMovedException |
分桶策略
将不同超时时间的会话分配到不同的桶中,做到有效管理,按照时间间隔来分桶
private long roundToNextInterval(long time) {
return (time / expirationInterval + 1) * expirationInterval;
}
会话建立之后,会话如何保持激活状态
问题 会话如何迁移?
会话激活的方法有 public synchronized boolean touchSession(long sessionId, int timeout) { //获取会话 SessionImpl s = sessionsById.get(sessionId); if (s == null) { logTraceTouchInvalidSession(sessionId, timeout); return false; } //关闭 if (s.isClosing()) { logTraceTouchClosingSession(sessionId, timeout); return false; } //更新会话 将旧过期时间桶中session移动到新桶 updateSessionExpiry(s, timeout); return true; }
client 什么时候会发出激活会话请求
1客户端向服务端发送请求,包含读写请求,就会激活会话
2 客户端发现在sessionTimeout/3时间内未收到任何通信,就会向服务器发起ping请求,
服务端收到请求后,就会进行会话激活操作
超时检测策略
对于会话超时检测而言,zookeeper使用SessionTracker负责,sessionTracker使用单独线程(超时检查线程)
专门进行会话超时检测,即逐个一次地对会话桶中剩余会话进行清理。
如果一个会话被激活,那么zookeeper会将其从上一个会话桶迁移到下一个会话桶中,
如ExpirationTIme 1的session n迁移到ExpirationTime n桶中,此时ExpirationTime 1中留下的会话就是没有被激活的
超时检测程序就定时检查这个会话桶中剩余未被迁移的会话,并且只在指定时间点上检查(ExpirationTime 1,ExpirationTime2,
ExpirationTime3,...n)这样有利于提高性能
@Override public void run() { try { while (running) { long waitTime = sessionExpiryQueue.getWaitTime(); if (waitTime > 0) { Thread.sleep(waitTime); continue; } for (SessionImpl s : sessionExpiryQueue.poll()) { ServerMetrics.getMetrics().STALE_SESSIONS_EXPIRED.add(1); setSessionClosing(s.sessionId); expirer.expire(s); } } } catch (InterruptedException e) { handleException(this.getName(), e); } LOG.info("SessionTrackerImpl exited loop!"); }
到此,相信大家对“zk中的会话管理SessionTrackerImpl的方法”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。