微服务系列(二)(2) ZooKeeper源码分析-part-1

微服务系列(二)(2) ZooKeeper源码分析-part-1

本节开始进行ZooKeeper的源码分析,针对Zookeeper Server的初始化过程,通讯原理及选举机制做源码层面上的介绍

作为ZooKeeper的使用者,应该知道如何部署和启动Zookeeper吧

看源码的入口就从这里作为出发点,找到zkServer.sh或者zkServer.cmd

截取zkServer.sh里的一段重要的命令

nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
"-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
-XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
-cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &

以及

ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"

找到了程序入口QuorumPeerMain

进入org.apache.zookeeper.server.quorum.QuorumPeerMain#main

具体链路就不追踪了,做了三件事:

  1. 加载配置文件
  2. 启动清除日志管理器(用于定时清除日志和快照数据)
  3. 启动ZooKeeperServerMain(单机模式下)或org.apache.zookeeper.server.quorum.QuorumPeerMain#runFromConfig(非单机模式下)

继续追踪ZooKeeperServerMain的启动过程

忽略JMX等相关内容,这里的启动同样加载了配置文件,并进入核心启动方法org.apache.zookeeper.server.ZooKeeperServerMain#runFromConfig

  1. MetricsProvider引导程序的初始化和启动,用于度量以及与外部系统交互,目前猜测与选举相关(官方注释:A MetricsProvider is a system which collects Metrics and publishes current values to external facilities.)

  2. FileTxnSnapLog初始化,用于把文件存储的日志和快照载入到JVM并定期写入文件(它会被包裹在ZKDatabase里,由ZKDatabase直接与ZooKeeperServer中的其他组件交互)

  3. ZooKeeperServer初始化和启动,启动有两种模式Netty和NIO,默认采用NIO模式启动,具体的启动步骤就不介绍了,无非是各种工作线程的初始化和启动、参数配置、端口配置、请求处理器配置等

  4. ContainerManager初始化和启动,用于定期检测容器情况,确保容器正常运行

这里我们需要关注的是ZooKeeperServer,关注它的startup()方法

public synchronized void startup() {
   
    if (sessionTracker == null) {
   
        createSessionTracker();
    }
    startSessionTracker();
    setupRequestProcessors();

    registerJMX();

    setState(State.RUNNING);
    notifyAll();
}

这里又出现了几个新的类:

  • SessionTracker:用于session信息的保存、创建、销毁、定时检测是否失效

  • RequestProcessor:用于请求处理,包括sync、send、commit等命令执行的操作

差不多到这里,单机模式下的ZooKeeperServerMain类,后面在看集群模式下的过程中会用到它的东西。

回归org.apache.zookeeper.server.quorum.QuorumPeerMain#runFromConfig

与单机模式不同的地方在于,它启动的是QuorumPeer而不是ZooKeeperServer

QuorumPeer初始化过程:

初始化权限相关的类QuorumAuthServerQuorumAuthLearner,分别用于认证server和learner。

QuorumPeer启动过程:

  1. 初始化zkDb(前面看到的包裹了FileTxnSnapLogZKDatabase),这里与单机模式下存在不同的地方,它额外增加了epoch校验的逻辑,不允许出现zxid大于当前epoch的情况。
  2. 启动ServerCnxnFactory(同单机模式下)
  3. 启动AdminServer(同单机模式下)
  4. 启动选举org.apache.zookeeper.server.quorum.QuorumPeer#startLeaderElection,重点来了!

org.apache.zookeeper.server.quorum.QuorumPeer#startLeaderElection

synchronized public void startLeaderElection() {
   
    try {
   
        //初始化自己持有的投票信息
        if (getPeerState() == ServerState.LOOKING) {
   
            currentVote = new Vote(myid, getLastLoggedZxid(), getCurrentEpoch());
        }
    } catch(IOException e) {
   
        RuntimeException re = new RuntimeException(e.getMessage());
        re.setStackTrace(e.getStackTrace());
        throw re;
    }
	//初始化选举算法类
    this.electionAlg = createElectionAlgorithm(electionType);
}
protected Election createElectionAlgorithm(int electionAlgorithm){
   
    Election le=null;

    //TODO: use a factory rather than a switch
    switch (electionAlgorithm) {
   
    case 1:
        //AuthFastLeaderElection已废弃
        le = new AuthFastLeaderElection(this);
        break;
    case 2:
        //AuthFastLeaderElection已废弃
        le = new AuthFastLeaderElection(this, true);
        break;
    case 3:
        QuorumCnxManager qcm = createCnxnManager();
        QuorumCnxManager oldQcm = qcmRef.getAndSet(qcm);
        if (oldQcm != null) {
   
            LOG.warn("Clobbering already-set QuorumCnxManager (restarting leader election?)");
            oldQcm.halt();
        }
        QuorumCnxManager.Listener listener = qcm.listener;
        if(listener != null){
   
            listener.start();
            FastLeaderElection fle = new FastLeaderElection(thi
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值