本篇内容主要讲解“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进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。