zookeeper - session建立(4)

概述

    在讲解完zookeeper核心的选举部分的功能逻辑之后,另外一个我个人觉得需要理解的就是zookeeper的client-server之间的连接的建立过程,因为除了zookeeper各个节点之间的通信外,另外一大块就是zookeeper作为server端与client端的交互,包括之前的连接建立以及后续的各种操作命令入get/set等操作,这个博文专注于讲清楚前面部分的概念,后面部分的逻辑会有专门的一篇博文来阐述。

    当然由于现在对于zookeeper的访问已经有很多开源的实现,排在首位的应该就是Curator了(最早介绍这个东西给我的还是我在车来了的同事袁翔,感谢当初带我入门),大部分情况我们使用的都是它封装的高级API,但是其实如果我们只是使用它的高级API而没有细究底层,我们还是不知道client-server之间的交互细节的,所以为了能够更直观的知道细节,我就在网上找了一个demo,基于这个demo我们可以开始开始我们的分析了。

zookeeper - session建立(4)_第1张图片
zookeeper-api

说明

    上面中我们看到的client通过new ZooKeeper的api创建了server的连接,然后开始的一系列操作,所以我们的源码分析也从这个地方开始。


zookeeper-session连接


Session建立 - client端

    通过demo我们看出来,client连接zookeeper的server端其实就是创建了zookeeper对象。

    创建zookeeper对象,核心的点是创建了ClientXnxn对象,该对象内部包含两个核心对象,分别是sendThread和eventThread。

    启动zookeeper对象,实际上是启动sendThread和eventThread。当然我们关注的是sendThread这部分的工作,基本上建立连接(session的建立)也就是它在玩转的。

    在sendThread当中我们需要处理各种连接事件,譬如注册OP_CONNECT/OP_WRITE/

OP_READ等相关事件。


zookeeper - session建立(4)_第2张图片
session-client-1

说明:

    Zookeeper当中主要是创建了ClientXnxn对象并进行启动,其中ClientCnxn对象内部主要对象是两个线程,分别是是sendThread和eventThread,其中sendThread负责连接server。


zookeeper - session建立(4)_第3张图片
session-client-2

说明:

    很明显的创建两个线程的逻辑,一个是sendThread,一个是eventThread。我们关注sendThread的run部分逻辑。


zookeeper - session建立(4)_第4张图片
session-sendThread-1

说明:

    sendThread关联的几个对象包括sessionId,outgoingQueue等。

    sendThread内部如果判断clientCnxnSocket没有建立连接,就会开始尝试建立连接。

    我们关注的应该就是建立连接的过程,关注startConnect部分逻辑。


zookeeper - session建立(4)_第5张图片
session-sendThread-2

说明:

    继续跟进connect部分的逻辑


zookeeper - session建立(4)_第6张图片
session-sendThread-3

说明:

    继续跟进registerAndConnect部分的逻辑


zookeeper - session建立(4)_第7张图片
session-sendThread-4

说明:

    首先将socket注册到selector当中并关注OP_CONNECT动作,这样异步连接成功的过程中就可以捕捉到事件了。

    如果立即连接成功以后就直接进入后续处理了,关注一下primeConnection这个动作,在异步连接成功后也会执行这个函数的。


zookeeper - session建立(4)_第8张图片
session-sendThread-5

说明:

    连接成功我们开始发送相关报文给server端,其中发送是通过放到outgoing队列中,有专门的发送线程负责发送。

    其实发送了两种报文,但是不知道前面的报文是什么东西,看着像各种watch。

    最后最重要的部分在于connectionPrimed部分操作,其实就是注册了OP_READ和OP_WRITE事件到selector当中了。


zookeeper - session建立(4)_第9张图片
session-sendThread-6

说明:

    其实这个run逻辑是在sendThread当中执行的,我们真正关心的部分逻辑是在doTransport部分,里面其实是对异步连接成功的处理。


zookeeper - session建立(4)_第10张图片
session-sendThread-7

说明:

    进入doTransport的逻辑我们看到了selector的执行部分,其中select返回的就是感兴趣的事件,我们在registerAndConnect逻辑当中注册了OP_CONNECT事件,所以假设异步连接成功了那么我们就再次进入了sendThread.primeConnection的逻辑。

    在处理OP_CONNECT事件逻辑,sendThread.primeConnection的逻辑其实就是在发送package报文。    

    在处理OP_READ和OP_WRITE的逻辑,进入的其实是doIO部分的逻辑。


zookeeper - session建立(4)_第11张图片
session-sendThread-8

说明:

    处理读事件也是一件挺有意思的事情,基本上你会看到ByteBuffer的各种用法,这里读取的逻辑其实很简单,先读取4Byte的数据长度,然后再读取剩余的实际报文数据。

    incomingBuffer一开始读取的是报文长度,在readLnegth()内部其实就是读取实际数据,根据sock.read(incomingBuffer)获取报文的长度。


zookeeper - session建立(4)_第12张图片
session-sendThread-9

说明:

    处理写事件,基本上就是发送报文,细节没仔细关注。


Session建立 - server端


    server端其实就是接收client端的连接,接受连接部分的逻辑似乎有点绕,所以我默认就从server端已经接受了连接并开始处理报文的逻辑开始。

    通过整个逻辑的串联了解下server对报文请求的处理,其实整个处理过程类似pipeLine的过程,由PrepRequestProcessor、SyncRequestProcessor、FinalRequestProcessor三者进行的串联。


zookeeper - session建立(4)_第13张图片
session-server-1

说明:

    开始进入处理connect请求部分的逻辑,入口函数已经很明显了。


zookeeper - session建立(4)_第14张图片
session-server-2

说明:

    进入创建session部分的逻辑,注意在这里生成了cnxn对象,session密码,超时时间等。


zookeeper - session建立(4)_第15张图片
session-server-3

说明:

    创建session其实一个异步过程,这了我们生成了一个Request对象,然后提交这个Request对象。


zookeeper - session建立(4)_第16张图片
session-server-4

说明:

    首先我们通过PrepRequestProcessor操作进行第一波处理,processRequest操作其实把request提交到一个队列当中submittedRequests当中,具体的消费处理逻辑看下一个逻辑代码。


zookeeper - session建立(4)_第17张图片
session-server-5

说明:

    没错,这里开始进行第一波处理了,看函数就是PrepRequestProcessor进行处理,具体处理逻辑往后继续看。


zookeeper - session建立(4)_第18张图片
session-server-6

说明:

    其实这个地方我们基本上知道了zookeeper处理请求的核心逻辑代码,我们只是现在关心session的create事件而已。


zookeeper - session建立(4)_第19张图片
session-server-7

说明:

    这里我们看到createSession部分的逻辑,继续关注pRequest2Txn逻辑。


zookeeper - session建立(4)_第20张图片
session-server-8

说明:

    我们将进行下一步下一步处理,至于nextProcessor从哪里来的呢,可以看下一个截图。

其实nextProcessor其实是syncProcessor。


zookeeper - session建立(4)_第21张图片
session-server-9

说明:

    基本上可以看出来了,PrepRequestProcessor、SyncRequestProcessor、FinalRequestProcessor。


zookeeper - session建立(4)_第22张图片
session-server-10

说明:

    只是把任务简单的提交了另外一个queue当中,也就是queuedRequests当中。


zookeeper - session建立(4)_第23张图片
session-server-11

说明:

    take任务继续下一步处理,这个还在SyncRequestProcessor当中,我们关注其实是flush动作,继续看下图的代码。



zookeeper - session建立(4)_第24张图片
session-server-12

说明:

    其实flush里面最后还是将任务提交到给FinalRequestProcessor进行处理。


zookeeper - session建立(4)_第25张图片
session-server-13

说明:

    进入zks.processTxn的逻辑,这部分代码其实很多,所以只截取了其中一部分。


zookeeper - session建立(4)_第26张图片
session-server-14

说明:

    把session加入到全局session当中。


zookeeper - session建立(4)_第27张图片
session-server-15

说明:

    真正完成session初始的入口函数。

zookeeper - session建立(4)_第28张图片
session-server-16

说明:

    一开始通过serverCnxnFactory.registerConnection将session注册到server端,将session创建的结果发送回client端。

zookeeper - session建立(4)_第29张图片
session-server-17

说明:

    在server端维持新建的session对象,但是我暂时也不知道干嘛。我们在创建ServerCnxnFactory的过程中会生成server端负责accept连接,这部分到时候后面再继续补充。


参考文献

使用ZooKeeper Java API编程

Zookeeper源码分析之二Session建立

你可能感兴趣的:(zookeeper - session建立(4))