問題
客戶端怎麼給server發請求?
猜測
parse 輸入的command 然後通過某種方式發給server。
預讀代碼
從客戶端main代碼org.apache.zookeeper.ZooKeeperMain
看起,看下怎麼給server發請求的。
慢慢追蹤到這:org.apache.zookeeper.ZooKeeperMain#processZKCmd
就是這裏:
假設我們現在要發一個create /test
實現類就是CreateCommand
parse不管
看exec函數
一通操作後走到了
org.apache.zookeeper.ZooKeeper#create(java.lang.String, byte[], java.util.List<org.apache.zookeeper.data.ACL>, org.apache.zookeeper.CreateMode)
(看參數少點這個)
於是我們可以看到是通過cnxn這個東西去submitRequest的。
再點進去,發現是通過packet發的
那packet是個啥?再點進去發現
調用packet.wait() 意思就是等待request完成
觸碰到知識盲點了:所有object都有wait(),調用的時候發生了什麼?
答:https://www.baeldung.com/java-wait-notify
就是線程suspend了,等待別人喚醒。
所以我們可以想象有別的地方會把這個packet喚醒,通知他請求發送完了。
注意packet是new queuePacket()
點進去可以發現有把packet放到隊列的邏輯:org.apache.zookeeper.ClientCnxn#queuePacket(org.apache.zookeeper.proto.RequestHeader, org.apache.zookeeper.proto.ReplyHeader, org.apache.jute.Record, org.apache.jute.Record, org.apache.zookeeper.AsyncCallback, java.lang.String, java.lang.String, java.lang.Object, org.apache.zookeeper.ZooKeeper.WatchRegistration, org.apache.zookeeper.WatchDeregistration)
這個接口有兩個實現,我們來看NIO的實現
org.apache.zookeeper.ClientCnxnSocketNIO#wakeupCnxn
就是selecor.wakeup()
把數據從socket寫出去
打斷點
那我們就把斷點打在org.apache.zookeeper.ZooKeeper#create(java.lang.String, byte[], java.util.List<org.apache.zookeeper.data.ACL>, org.apache.zookeeper.CreateMode)
唄
環境準備
可以參考: https://blog.csdn.net/waltonhuang/article/details/106071393
server 1 debug啓動
server 2、3 run 啓動
server1是follower。
客戶端連接server1,debug方式啓動
寫請求create /test
發給server1。
成功斷點在了我們斷點的地方:開心
一路確實走到了咱們的NIO的wakeUpCnxn
結束!完美按照我們設想的路子走到了最後!
回答問題
通過NIO把packet,經過socket,發送給了server