概述
之是以會有這篇文章,是因為我原本想理清楚叢集模式下client連接配接follower的場景下發起寫操作,如何被路由到leader以及leader如何通過兩階段送出最終持久化資料 ,但是在這個過程中我發現需要一些前置過程需要理一理,否則了解那個複雜的過程會特别饒,基于将複雜邏輯進行拆分的原則,就有這篇文章。
server啟動過程
啟動過程分析
zookeeper叢集當中所有的節點都會預設啟動accept線程,負責接收client的連接配接,劃重點啊,是所有的節點都會建立client的accept線程。
整個啟動過程如下圖所示,基本上就是分為三步走,
1、通過ServerCnxnFactory建立NIOServerCnxnFactory并進行基本的配置(配置其實就是建立acceptor線程和selector線程);
2、建立QuorumPeer對象并将NIOServerCnxnFactory注入;
3、啟動QuorumPeer對象并将NIOServerCnxnFactory進行啟動,然後acceptor線程就位了,selector線程就位了。整個服務就啟動了。
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuEmZ3AzN3gTOmVjM5IWZmRWYwY2NiRzM5YDMkZjNjdDNfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
QuorumPeer啟動過程
啟動過程源碼
整體流程
說明:
整體流程包括建立工廠、建立quorumPeer對象,注入工廠并啟動quorumPeer對象。
建立工廠
建立工廠的過程,其實我們可以看出來這裡其實是建立的NIOServerCnxnFactory對象。
設定工廠參數中初始變量
初始化NIOServerCnxnFactory對象,裡面主要建立了acceptor的socket對象、線程;建立了selector對象的線程數。
啟動過程
啟動了NIOServerCnxnFactory對象。
實際執行啟動的過程
真正是啟動了acceptThread和selectorThreads。
leader啟動過程
啟動過程分析
在leader啟動過程中,核心點在于啟動quorumPeer通信的socket的accept線程,然後通過accept線程去accept其他learner等連接配接,針對每個learner的連接配接我們都啟動一個LearnerHandler線程進行處理。
Leader時序圖
leader-1
通過makeLeader建立leader,通過leader.lead()方法啟動服務。
leader-2
綁定quorumPeer之間通信的socket。
leader-3
啟動LearnerCnxAcceptor線程,負責接收learner的連接配接且為每個連接配接啟動一個線程。
leader-4
follower/observer啟動過程
follower和observer的啟動過程其實就是一個建立follower對象并向leader發起連接配接的過程。
follower時序圖
follower-1
建立follower。
follower-2
連接配接leader,并不停的讀取和處理封包。
server-accept過程
server的accept過程由AcceptThread線程負責接收新的socket,然後從selectorThreads當中選取一個selector對象(輪詢選擇selector)進行注冊。
注冊後由selectorThread會通過selector處理注冊到這個線程的socket,并進行後續的讀寫操作。
AcceptThread繼續處理新的連接配接到來,并注冊到selectorThread當中。
AcceptThread處理連接配接過程
accept-1
循環執行過程中擷取accept的socket。
accept-2
執行doAccept過程,内部負責accept新的socket。
accept-3
針對accept的socket選擇一個selectorThread進行注冊。
accept-4
每次先執行待讀取的資料,然後注冊新accept的socket。
accept-5
核心的關鍵點在于注冊到selectorThread的selector當中。