zookeeper客户端与服务端交互流程源码解析

客户端发送请求和接收请求。

图1

图1 zkCll.sh 启动时会调用zookeeperMain() 方法。古这是入口。

图2

 图2 290行 new ZookeeperMain , 297行连接zk  

图3

 

图 3 277 判断zk的状态,  281行设置只读,  282行 new Zookeeper()

图4

图4 445 行赋值watcher给默认的defaultWatcher. 447行对地址进行处理, 447行包装地址。

图5

图5 如果 写多个地址的话zookeeper回随机选择一个地址连接,如果这个地址挂了,他会从其他的地址再从新选一个连接。 

图6

图7

图8

图6 图7 图8 意思是 传进来的地址 以逗号截取,然后每一个地址再以":" 分号截取,封装到inetSocketAddressHolder类中,然后把 inetSocketAddressHolder 放在一个ArrayList中serverAddresses中。

图9

图10

图 9 图10没有做jut具体的事情,104行 打乱的意思(图10),换句话说就是随机地址连接。

图10

图11

ClientCnxSockNIO

图12

图11 图12 1884行先拿 图12 的key 去配置文件中查找是否配置这个名字,如果没有配置ClientCnxSockNIO 的全类名,然后反射实例化返回。

图13

13

图13初始化Zookeeper参数值,创建两个线程。

图14

图15

 

图16

图14,图15,图16 启动两个线程,SendThread 继承ZookeeperThread  这个线程。Zookeerper线程继承Thread线程。

图17

 

 

图17-0

17-1

图17-1

图17-2

图17-3

图17-4

图17-5

图17-6

图17-7

 

图17-8

图17-9

图17-9 80行如果还没有初始化,等待连接返回的结果图17-12。92行如果初始化完了,改为true 。94行  客户端发送后,如何响应呢,94行sendThread.readRespone() 用这个线程读取响应结果图17-15。

图17-10

图17-11

图17-12

图17-12核心方法 为146行调用另一个线程的onConnected的方法图17-13

图17-13

图17-13  1312行如果连接成功 本地注册一个Watcher的None事件。

图17-14

图17-15

4

图17-15  通过判断xid的值来分别处理,-2 ping的处理,-4验证,-1 客户端接收服务的的事件。 823行 packet的replyHeader的xid和replyHdr的xid一致时,把replyHdr的请求头信息从新封装到packet中,842行中,如果服务端返回信息,同样把新增加的服务端返回信息封装到 packet中. replyHdr是什么呢,是把从参数传入的流信息进行解析转换为replyHdr,此时这个replyHdr没有response信息。850行完成通知图17-16

图17-16

图17-16 完成唤醒操作。

 

图17 为SendThread 的run()方法。图17 图18  1044行 默认状态为未连接状态。如果不是关闭状态和验证失败状态就是活着的状态图19 ;1046行如果未连接,是第一次连接1047行的if判断. 会走1062行 ,从hostPovider选取一个地址,进行socket连接。 1100行为读取超时= 设置的超时时间 减去 当前时间距离上次读取时间(now -上次读取时间)<0 则认为是超时,或者,设置的连接事件 减去当前时间距离上次发送时间(now -上次发送时间)小于0认为连接超时则抛出异常sessionTimeOutException。然后try catch捕获异常,程序不会中止,继续执行while循环,1044行;当第一次connect()方法时 图17-1,图17-2,图17-3 方法 把isFirstConnect置为false,当抛出sessionTimeOutException 异常时,进入1047行到1053行睡眠一段时间。1062行 ,图17-4 默认超时情况下从新从其他的地址中选取一个地址,不会是上一次执行的地址,因为会采用取余数的方式,图17-4;图1115行连接成功,就返送ping.图17-5 ,和发送逻辑一致,只不过类型为OpCode.ping ;xid=-2. ; 1115行连接成功  后1145行 客户端发送数据 

图17 到图17-14 总结; 首先1.初始化 SendThread线程 ,初始化 socket  ;  2.zookeeper 创建一条命令,然后这个命令加到 request  ,把Request 变成Packet ,最后放在outgoingQueue队列中。sendThread 线程中有一个while(){ 1.如果socket没有连接就去连接,2,如果socket连接成功了,客户端会发送一个ConnectRequest, 接受服务端返回的ConnectResponse(Envent.none)  3,如果连接成功,从outgoingQueue 队列中取出packet ,通过socket发送出去,同时,如果说 有结果。penedingqueue里面回去放等待结果的packet} 

图18

图19

图20

图20 995行 改变状态为 正在连接,conecting . 设置名字。999行到1018行不重要,1019行打印日志不重要。 1021行socket连接。

图21

图22

图23

 

图24

图23  连接socket  ClientCnxnSocket 接口 的 connect() 方法,他有唯一的实现类ClientCnxnSocketNIO的connect()方法图24.

  首先创建一个socket图25. 287行 注册一个socket图26.

图25

图26

图26  276行注册一个连接事件,277行 判断是不是立即连接成功,如果是调用primeConnection()方法。 

图27

总结 ;



图28-0 

图28-0 290行为执行完成以后,执行291行命令行的run()方法。  

图28

图28 314行,316行为java 的命令行实现类。332行为核心的实现类方法 图31。执行命令 图30命令行前缀对应的代码 图29;

图29

图30

图31

图31 如果命令不为空,加入命令,加入历史,处理命令。命令次数加1.重点是372行。

 

图32

图33

图33 689行创建命令 如果有-e,-s 为创建临时有序节点,如果 -e 就是临时节点,-s就是持久节点顺序 704行返回权限列表图34 ,707行调用zk 创建节点。709行打印命令 。649行推出命令调用了zk.close()方法图 36

图34

图35

图36

 

 

图37

图37 777行验证path ,传一个是否顺序节点标志。如果是顺序节点会在path上固定加上+1图38  ;779行创建一个根目录图40;781行构建一个请求头图41,设置一个类型为create 图42 ,构建一个createRequest , createResponse请求, 设置内容,标记,path, 权限,792行 submitRequest 图43,通过socket 发送请求到服务端,获取相应头,判断相应头是否有错误信息,有抛出异常,如果没有,拿到path返回。

图38

图39

 

图39验证path , 如果path的首字符不是/抛出异常,如果最后一位是/ 抛出异常,如果 -s 最后一位是/不会抛出异常,为什么吗,因为顺序节点默认+1了,最后一位就是1了,不会抛出异常。

图40

加了一个根路径

图41

 

图42

图43

图43  1407行 发送 queuePacket  一直阻塞等待直到 完成,才会唤醒,ReplyHeader有值才会返回。 

图44

图44 把传进来的header,request,respolnse等等参数封装到yigePacket对象里,燃油放在一个outgoingQueue队列中。

 



服务端 接收请求和发送请求

图45

图2

判断是单机模式还是集群模式的标记是 有没有 图2的7行到10行。

图3

图4

图5

 

图5  104 行把传过来的参数解 析为QuorumPeerConfig对象,并为这个对象的属性赋值,图6;113判断 servers是不是大于0,是则是集群模式,反之为单机模式。

图6

图6 属于配置类 图7配置文件的类。

图7

图8

图8145行把配置文件通过流的形式转换为Properties文件,键值对的形式。152行开始解析图9

图9

 

 

图9 229行 判断如果是observer ,设置一个observer标记,如果有这个标记则放在observers属性中其他放在servers 中。其他都是赋值操作。399行有一个过半校验的逻辑图10 ,可以发现过半校验并没有observer。

图10

图10为过半机制。

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值