持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第28天,点击查看活动详情
Zookeeper核心启动源码流程描述
首先是找到QuorumPeerMain主启动类
运行main方法,首先是加载zokeeper的配置文件,也就是zoo.cfg文件解析成QuorumPeerConfig配置文件,接下来运行runFromConfig(QuorumPeerConfig config)真正的开启运行一个节点;
-
创建一个服务端连接工厂。代码逻辑中会获取系统参数,参数中传入了指定的netty作为服务端连接对象,如果不传则默认是创建一个NIOServerCnxnFactory,最终创建出ServerCnxnFactory,然后在对这个连接对象配置其他参数;
-
接下来就是获取到当前节点quorumPeer = getQuorumPeer(),然后做的事情就是给这个节点从config配置文件中给他赋值;
-
启动节点quorumPeer.start()
-
加载数据,开启netty服务绑定启动端口;
-
开始leader选举算法(startLeaderElection)
createElectionAlgorithm(int electionAlgorithm) 创建选举算法 返回Election
参数默认传的3,
初始化一个节点选举的管理器,开启节点选举器额监听线程;listener.start();
Listener extends ZooKeeperThread 是一个线程类,主要的业务逻辑在他的run方法;
-
-
listener.start()---------->run()
新建了一个ServerScoket连接,绑定当前节点的选举端口,监听客户端accept连接事件,然后就是receiveConnection(client)接收处理客户端事件;
handleConnection(sock, din) sock就是客户端 din是客户端的输入流;处理客户端连接;
上来是从输入流读取发送选票的机器id,判断机器码跟自己的机器码对比大小
-
如果当前机器的id比收到的机器id大
那么当前节点主动断开与这个机器的scoket连接,并且主动发起scoket连接到这台机器,zk不允许机器id小的向大id主动发起连接,scoket是双向的,这样做也可以避免各个节点之间的重复连接;
-
如果机器id相等
则This should be either a configuration error, or a bug 证明是个bug
-
另外就是主逻辑,当前的机器id比接收到的小;
开启两个工作线程去处理数据,SendWorker和RecvWorker线程;
同样是两个run()方法
sw---->run():主要做的就是从队列里面拿到选票,输出流的形式循环发送出去;
rw----->run():接受线程读取选票封装成message,添加到ArrayBlockingQueue recvQueue队列;
-
-
初始化快速选举算法,开启选举算法 FastLeaderElection fle = new FastLeaderElection(this, qcm); fle.start();
快速选举算法线程的启动流程:
-
首先开启两个线程的start方法,WorkerSender and WorkerReceiver
-
WorkerSender 工作发送线程
从队列LinkedBlockingQueue sendqueue;中获得消息信息 ToSend类型,里面包含着消息各种信息
把tosend消息中的字段值取出来构建成ByteBuffer,发送选票;
判断:如果选票的机器id就是自己,那么就把消息存放到public final ArrayBlockingQueue recvQueue;队列;
如果不是自己则把选票信息发送出去,并且建立相应的scoker连接;
-
WorkerReceiver 工作线程接收
首先就是循环轮训,从 ArrayBlockingQueue recvQueue队列中取出message消息‘
判断当前节点的状态是LOOKING还是其他分别作出不同的逻辑处理;
LOOKING: 如果节点状态是looking的话,则证明当前集群仍然在选举状态,还未选出leader;
如果发送选票状态是LOOKING状态,并且选举周期小于自己的周期,则把自己选举出来的结果发送给选票发送方sendqueue.offer(notmsg);
如果不是则代表系统已经选出leader了,则把本机认为的leader发送给对方;