在上一篇,咱們瞭解了zookeeper最基本的配置,也從中瞭解一些配置的做用,那麼這篇文章中,咱們將介紹Zookeeper的啓動過程,咱們在瞭解啓動過程的時候還要回過頭看看上一篇中各個配置參數在啓動時的位置。java
Zookeeper的啓動入口在org.apache.zookeeper.server.quorum.QuorumPeerMain。apache
在這個類的main方法裏進入了zookeeper的啓動過程,首先咱們會解析配置文件,即zoo.cfg和myid。編程
這樣咱們就知道了dataDir和dataLogDir指向哪兒了,而後就能夠啓動日誌清理任務了(若是配置了的話)。socket
DatadirCleanupManager purgeMgr = new DatadirCleanupManager(config .getDataDir(), config.getDataLogDir(), config .getSnapRetainCount(), config.getPurgeInterval()); purgeMgr.start();
接下來會初始化ServerCnxnFactory,這個是用來接收來自客戶端的鏈接的,也就是這裏啓動的是一個tcp server。在Zookeeper裏提供兩種tcp server的實現,一個是使用java原生NIO的方式,另一個是使用Netty。默認是java nio的方式,一個典型的Reactor模型。由於java nio編程並非本文的重點,因此在這裏就只是簡單的介紹一下。tcp
//首先根據配置建立對應factory的實例:NIOServerCnxnFactory 或者 NettyServerCnxnFactory
ServerCnxnFactory cnxnFactory = ServerCnxnFactory.createFactory();
//初始化配置 cnxnFactory.configure(config.getClientPortAddress(),config.getMaxClientCnxns());
建立幾個SelectorThread處理具體的數據讀取和寫出。this
先是建立ServerSocketChannel,bind等spa
this.ss = ServerSocketChannel.open(); ss.socket().setReuseAddress(true); ss.socket().bind(addr); ss.configureBlocking(false);
而後建立一個AcceptThread線程來接收客戶端的鏈接。線程
這一部分就是處理客戶端請求的模塊了,若是遇到有客戶端請求的問題能夠看看這部分。日誌
接下來就進入初始化的主要部分了,首先會建立一個QuorumPeer實例,這個類就是表示zookeeper集羣中的一個節點。初始化QuorumPeer的時候有這麼幾個關鍵點:code
1. 初始化FileTxnSnapLog,這個類主要管理Zookeeper中的操做日誌(WAL)和snapshot。
2. 初始化ZKDatabase,這個類就是Zookeeper的目錄結構在內存中的表示,全部的操做最後都會映射到這個類上面來。
3. 初始化決議validator(QuorumVerifier->QuorumMaj) (其實這一步,是在配置)。這一步是從zoo.cfg的server.n這一部分初始化出集羣的成員出來,有哪些須要參與投票(follower),有哪些只是observer。還有決定half是多少等,這些都是zookeeper的核心。在這一步,對於每一個節點會初始化一個QuorumServer對象,而且放到allMembers,votingMembers,observingMembers這幾個map裏。並且這裏也對參與者的個數進行了一些判斷。
4. leader選舉 這一步很是重要,也是zookeeper裏最複雜而最精華的一部分。
到這裏,咱們的zookeeper就啓動完成了。後面我將會分三部分進一步深刻理解zookeeper:
1. leader選舉
2. 存儲
3. 處理客戶端請求