​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求

问题​

客户端怎么给server发请求?

猜测

parse 输入的command 然后通过某种方式发给server。

预读代码

从客户端main代码org.apache.zookeeper.ZooKeeperMain看起,看下怎么给server发请求的。
慢慢追踪到这:org.apache.zookeeper.ZooKeeperMain#processZKCmd
就是这里:​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求
假设我们现在要发一个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)(看参数少点这个)

​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求
于是我们可以看到是通过cnxn这个东西去submitRequest的。
再点进去,发现是通过packet发的
​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求
那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)
​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求
这个接口有两个实现,我们来看NIO的实现
org.apache.zookeeper.ClientCnxnSocketNIO#wakeupCnxn
就是selecor.wakeup()
把数据从socket写出去
​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求

打断点

那我们就把断点打在org.apache.zookeeper.ZooKeeper#create(java.lang.String, byte[], java.util.List<org.apache.zookeeper.data.ACL>, org.apache.zookeeper.CreateMode)
​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求

环境准备

可以参考: ​https://blog.csdn.net/waltonhuang/article/details/106071393

server 1 debug启动
server 2、3 run 启动
server1是follower。

客户端连接server1,debug方式启动

​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求

写请求create /test发给server1。

​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求

成功断点在了我们断点的地方:开心
​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求
一路确实走到了咱们的NIO的wakeUpCnxn

结束!完美按照我们设想的路子走到了最后!

回答问题

通过NIO把packet,经过socket,发送给了server

奇怪的知识增加了!

​带着问题撸源码系列-zookeeper-客户端怎么给sever发请求