源码项目zookeeper-3.6.3:核心工作流程
ZooKeeper选举和状态同步结束之后的服务启动
在Leader的lead()方法的最后,即Leader完成了和集群过半Follower的同步之后,就会调用startZkServer()来启动必要的服务,主要包括:
SessionTracker
RequestProcessor
更新Leader ZooKeeperServer的状态
Leader.lead(){
startZkServer(){
zk.startup(){
//ZooKeeperServer启动
super.startup(){
startupWithServerState(State.RUNNING);
}
//ZK Container ZNode定时清除任务
if(containerManager != null){
containerManager.start();
}
}
}
}
同理,Follower也是一样的,在完成了和Leader的状态同步之后,也就是接收到Leader发送过来的NEWLEADER消息的时候,先拍摄快照,然后调用zk.startupWithoutServing()来启动Follower必要的一些基础服务,包括:
SessionTracker
RequestProcessor
更新Leader ZooKeeperServer的状态
Leader.syncWithLeader(long newLeaderZxid){
//创建SessionTacker
zk.createSessionTracker();
//启动一些服务
zk.startupWithoutServing(){
startupWithoutServerState(State.INITIAL);
}
}
不管Leader还是Follower,最后都执行startupWithServerState(State state),具体实现:
ZooKeeperServer.startupWithServerState(State state){
//创建和启动SessionTracker 重要
if(sessionTracker == null){
createSessionTracker();
}
startSessionTracker();
//初始化RequestProcessors 重要
setupRequestProcessors();
//其他各项基础服务
startRequestThrottler();
registerJMX();
startJvmPauseMonitor();
registerMetrics();
//更新状态为RUNNING
setState(state);
//解除其他线程的阻塞
notifyAll();
}
ZooKeeper SessionTracker启动和工作机制
需求背景:现在每个客户端链接到ZK服务器的时候,在服务器内部,都会创建一个Session来管理这个链接
如果链接断开,删除这个session
如果链接超时,删除这个session(在规定的超时时间前,没有任何动作)
会遇到什么问题?大量的session管理,ZK提供的方案:桶管理机制(Session管理,Connection管理)
在Leader启动的时候,Leader会创建LeaderSessionTracker,在Follower启动的时候,内部会创建一个LearnerSessionTracker。SessionTracker的内部都有globalSessionTracker和localSessionTracker之分,都通过SessionTrackerImpl和ExpiryQueue来完成Session管理。
SessionTrackerImpl的定义:时间轮
public class SessionTrackerImpl extends ZooKeeperCriticalThread implements SessionTracker {
// 存储 session 信息,key 是 sessionID, value 是 Session 对象
protected final ConcurrentHashMap<Long,SessionImpl> sessionById = new ConcurrentHashMap<Long,SessionImpl>();
// SessionTrackerImpl 本身是一个线程
// 注意这个数据结构,这是理解 Session 和 Connection 超时管理的关键,是一个类似于 时间轮 的数据结构设计
// 将所有要进行管理的 Session 或者 Connection 加入到不同时刻对应的某个队列中,ZK 只会每隔一段时间,针对一个队列,进行全部过期操作处理
private final ExpiryQueue<SessionImpl> sessionExpiryQueue;
// 存储 session 的超时时间信息,key 是 sessionID, value 是 超时时间
private final ConcurrentMap<Long,Integer> sessionWithTimeout;
// SessionTrackerImpl 本身是一个线程
public void run() {
try {
while(running) {
// TODO 注释: 获取下一个队列的超时时间,等待
long waitTime = sessionExpiryQueue.getWaitTime();
if(waitTime > 0) {
Thread.sleep(waitTime);
continue;
}
// TODO 注释: 执行 expire
for(SessionImpl s : sessionExpiryQueue.poll()) {
ServerMetrics.getMetrics().STALE_SESSIONS_EXPIRED.add(1);
setSessionClosing(s.sessionId);
expirer.expires(s);
}
}
} catch(InterruptedException e) {
handleException(this.getName(), e);
}
LOG.info("SessionTrackerImpl exited loop!");
}
public synchronized boolean touchSession(long sessionId,int timeout) {
SessionImpl s = sessionsById.get

文章详细阐述了ZooKeeper在选举和状态同步后的服务启动过程,包括Leader和Follower的角色。重点介绍了SessionTracker的工作机制,使用时间轮和ExpiryQueue管理Session,确保超时和断开连接的处理。同时,概述了Leader和Follower的RequestProcessor初始化流程,以及客户端和服务端的初始化步骤。
最低0.47元/天 解锁文章
2658

被折叠的 条评论
为什么被折叠?



