Zookeeper核心启动源码流程描述(一)

312 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 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,判断机器码跟自己的机器码对比大小

    1. 如果当前机器的id比收到的机器id大

      那么当前节点主动断开与这个机器的scoket连接,并且主动发起scoket连接到这台机器,zk不允许机器id小的向大id主动发起连接,scoket是双向的,这样做也可以避免各个节点之间的重复连接;

    2. 如果机器id相等

      则This should be either a configuration error, or a bug 证明是个bug

    3. 另外就是主逻辑,当前的机器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发送给对方;