天天看點

Zookeeper學習之路-源碼-用戶端(二)

目錄

從哪裡開始閱讀​

用戶端是怎麼連接配接伺服器的

從哪裡開始閱讀

我們可以從zk自帶的腳本中入手,一般都是在安裝目錄/bin 下面,然後我們發現有一個 zkCli.sh 的 shell檔案

Zookeeper學習之路-源碼-用戶端(二)

使用cat zkCli.sh 打開sh檔案,發現在最下面有這麼一行,org.apache.zookeeper.ZookeeperMain,和tomcat差不多,那麼就找到了源碼的入口,此處應該有掌聲。

Zookeeper學習之路-源碼-用戶端(二)

用戶端是怎麼連接配接伺服器的

為了和本人保持一緻, 建議使用maven 添加pom依賴,想必聰明的你,這個對你來說是小菜一碟把

<dependency>
  <groupId>org.apache.zookeeper</groupId>
  <artifactId>zookeeper</artifactId>
  <version>3.4.12</version>
</dependency>
           

代碼流程:

################初始化

org.apache.zookeeper.ZooKeeperMain#main  //主函數

org.apache.zookeeper.ZooKeeperMain#ZooKeeperMain(java.lang.String[]) //構造函數

org.apache.zookeeper.ZooKeeperMain.MyCommandOptions#parseOptions //解析參數

org.apache.zookeeper.ZooKeeperMain#connectToZK //連接配接到ZK

org.apache.zookeeper.ZooKeeper#ZooKeeper(java.lang.String, int, org.apache.zookeeper.Watcher, boolean) 使用原生zk

//會預設構造一個MyWatcher

org.apache.zookeeper.ClientCnxn //建立zk上下文

       在建立上下文的同時,會額外的建立兩個線程,一個 SendThread(用來發送cmd),一個EventThread(用來監聽)

   org.apache.zookeeper.ClientCnxn#start  //啟動上下文,在這個裡面其實是啟動了  sendThread.start(), eventThread.start()

###############初始化過程完畢

############### main()函數運作

org.apache.zookeeper.ZooKeeperMain#run   //運作main函數

org.apache.zookeeper.ZooKeeperMain#executeLine  //執行用戶端的指令行  cmd

org.apache.zookeeper.ZooKeeperMain#addToHistory 添加到曆史記錄中去,

HashMap<Integer,String> history = new HashMap<Integer,String>( );
           

org.apache.zookeeper.ZooKeeperMain#processCmd //處理指令 -cmd 

org.apache.zookeeper.ZooKeeperMain#processZKCmd //正是處理  有點像spring 中   xxx-> doxxx的韻味

      将指令通過比對的方式解析,不過是從之前的cmd解析中map中直接擷取的,

對于 create指令來說,使用原生的zk來建立

org.apache.zookeeper.ZooKeeper#create(java.lang.String, byte[], java.util.List<org.apache.zookeeper.data.ACL>, org.apache.zookeeper.CreateMode)

org.apache.zookeeper.proto.CreateRequest  //建立請求頭

org.apache.zookeeper.proto.CreateResponse //建立傳回

org.apache.zookeeper.ClientCnxn#submitRequest  //送出請求

sendThread.getClientCnxnSocket().wakeupCnxn(); 發送指令

org.apache.zookeeper.ClientCnxn#queuePacket  包裝成一個  Packet

有一個outgoingQueu隊列,用于存儲發送的指令

在org.apache.zookeeper.ClientCnxn#submitRequest 中是阻塞的,隻有完成的時候才會傳回ReplyHeader

###############回到前面說的 SendThread

既然是線程  就找 run 方法

org.apache.zookeeper.ClientCnxn.SendThread#run

org.apache.zookeeper.ClientCnxnSocket#doTransport(pendingQueue , outgoingQueue ) // 資料傳輸

outgoingQueue 發送的, pendingQueue 發送沒有傳回的

java.nio.channels.Selector#select(long) 使用 NIO的方式  像nio注冊SelectionKey.OP_CONNECT事件

等待處理完成,會收到通知

繼續閱讀