之所以会有这篇文章,是因为我原本想理清楚集群模式下client连接follower的场景下发起写操作,如何被路由到leader以及leader如何通过两阶段提交最终持久化数据 ,但是在这个过程中我发现需要一些前置过程需要理一理,否则理解那个复杂的过程会特别饶,基于将复杂逻辑进行拆分的原则,就有这篇文章。
zookeeper集群当中所有的节点都会默认启动accept线程,负责接收client的连接,划重点啊,是所有的节点都会创建client的accept线程。
整个启动过程如下图所示,基本上就是分为三步走,
1、通过ServerCnxnFactory创建NIOServerCnxnFactory并进行基本的配置(配置其实就是创建acceptor线程和selector线程);
2、创建QuorumPeer对象并将NIOServerCnxnFactory注入;
3、启动QuorumPeer对象并将NIOServerCnxnFactory进行启动,然后acceptor线程就位了,selector线程就位了。整个服务就启动了。
说明:
整体流程包括创建工厂、创建quorumPeer对象,注入工厂并启动quorumPeer对象。
说明:
创建工厂的过程,其实我们可以看出来这里其实是创建的NIOServerCnxnFactory对象。
说明:
初始化NIOServerCnxnFactory对象,里面主要创建了acceptor的socket对象、线程;创建了selector对象的线程数。
说明:
启动了NIOServerCnxnFactory对象。
说明:
真正是启动了acceptThread和selectorThreads。
在leader启动过程中,核心点在于启动quorumPeer通信的socket的accept线程,然后通过accept线程去accept其他learner等连接,针对每个learner的连接我们都启动一个LearnerHandler线程进行处理。
说明:
通过makeLeader创建leader,通过leader.lead()方法启动服务。
说明:
绑定quorumPeer之间通信的socket。
说明:
启动LearnerCnxAcceptor线程,负责接收learner的连接且为每个连接启动一个线程。
follower和observer的启动过程其实就是一个创建follower对象并向leader发起连接的过程。
说明:
创建follower。
说明:
连接leader,并不停的读取和处理报文。
server的accept过程由AcceptThread线程负责接收新的socket,然后从selectorThreads当中选取一个selector对象(轮询选择selector)进行注册。
注册后由selectorThread会通过selector处理注册到这个线程的socket,并进行后续的读写操作。
AcceptThread继续处理新的连接到来,并注册到selectorThread当中。
说明:
循环执行过程中获取accept的socket。
说明:
执行doAccept过程,内部负责accept新的socket。
说明:
针对accept的socket选择一个selectorThread进行注册。
说明:
每次先执行待读取的数据,然后注册新accept的socket。
说明:
核心的关键点在于注册到selectorThread的selector当中。