天天看点

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事件

等待处理完成,会收到通知

继续阅读