Zookeeper服務器啟動


1 單機版啟動

單機版啟動大致可以分為如下步驟:

  • 配置文件解析
  • 初始化數據管理器
  • 初始化網絡IO管理器
  • 數據恢復
  • 對外服務

image

1.1 預啟動

QuorumPeerMain作為啟動類,該類會進行如下操作:

  • 解析zoo.cfg配置文件
  • 清理歷史數據
  • 根據配置文件中服務器地址列表的數量,判斷是單機還是集群啟動
  • 創建ZooKeeperServerMain真正啟動ZK服務器

注意:QuorumPeerMain作為啟動類,是在zkServer.sh腳本中進行的配置。

1.2 初始化並啟動

ZooKeeperServerMain作為真正啟動單機版ZK服務器的核心實現,ZK服務器的啟動包括兩個方面:

  • 網絡IO管理(ServerCnxnFactory):監聽2181端口,用於處理客戶端網絡請求處理
  • 服務啟動(ZookeeperServer)

    ① 加載數據
    ② 應用會話管理
    ③ 創建請求處理鏈
    ④ 將ServerCnxnFactory注冊到ZookeeperServer中,以便ZookeeperServer可以利用ServerCnxnFactory獲取到客戶端請求。

Zookeeper使用鏈式方式處理客戶端請求,單機版啟動時,初始化的處理鏈如下:
image

2 集群版啟動

image

QuormPeer類是集群啟動過的核心實現:

  • 啟動ServerCnxnFactory接收客戶端請求
  • 初始化Leader選舉算法

    根據zoo.cfg文件中的electionArg屬性的值,創建相應的選舉算法,默認提供了3中算法:

    • LeaderElection(已廢棄)
    • AuthFastLeaderElection(已廢棄)
    • FastLeaderElection:
  • 啟動QuormPeer線程

    選舉流程、執行Leader流程、Follower流程、Observer流程

2.1 初始化選舉算法

QuorumPeer中會首先獲取選舉算法,代碼如下:

// 代碼已經省略所有try{} catch{}部分
synchronized public void startLeaderElection() {
    currentVote = new Vote(myid, getLastLoggedZxid(), getCurrentEpoch());
    for (QuorumServer p : getView().values()) {
        if (p.id == myid) {
            myQuorumAddr = p.addr;
            break;
        }
    }
    if (myQuorumAddr == null) { /* 異常省略 */ }
    if (electionType == 0) {
        udpSocket = new DatagramSocket(myQuorumAddr.getPort());
        responder = new ResponderThread();
        responder.start();
    }
    this.electionAlg = createElectionAlgorithm(electionType);
}
protected Election createElectionAlgorithm(int electionAlgorithm){
    Election le=null;
    //此處使用工廠類更加適合
    switch (electionAlgorithm) {
    case 0:
        le = new LeaderElection(this);
        break;
    case 1:
        le = new AuthFastLeaderElection(this);
        break;
    case 2:
        le = new AuthFastLeaderElection(this, true);
        break;
    case 3:
        qcm = createCnxnManager();
        QuorumCnxManager.Listener listener = qcm.listener;
        if(listener != null){
            listener.start();
            le = new FastLeaderElection(this, qcm);
        } else {
            LOG.error("Null listener when initializing cnx manager");
        }
        break;
    default:
        assert false;
    }
    return le;
}

2.2 異步線程根據服務器角色進入相應流程

集群啟動會在QuormPeer的異步線程中循環判斷服務器的狀態,以便執行服務器相應的流程,簡易代碼如下:

while (running) {
    switch (getPeerState()) {
        case LOOKING:
            setCurrentVote(makeLEStrategy().lookForLeader());
            break;
        case OBSERVING:
            setObserver(makeObserver(logFactory));
            observer.observeLeader();
            break;
        case FOLLOWING:
            setFollower(makeFollower(logFactory));
            follower.followLeader();
            break;
        case LEADING:
            setLeader(makeLeader(logFactory));
            leader.lead();
            setLeader(null);
            break;
        }
    }
}

3 選舉算法

待補充


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM