Zookeeper 客户端源码吐血总结

本文深入剖析Zookeeper客户端源码,从关键类到连接流程,包括创建Zookeeper实例、建立连接、IO读写,以及EventThread和SendThread的工作原理。通过对源码的解读,帮助理解Zookeeper客户端与服务器之间的交互机制。
摘要由CSDN通过智能技术生成

目录
一、几个重要的类
二、JAVA的基础知识
三、大致了解
四 从入门到放弃的讲解
Code1:ZK
Code2:创建 Zookeeper实例,实例化ClientCnxn,实例化ClientCnxnSocketNIO
Code3:实例化ClientCnxnSocketNIO (which extends ClientCnxnSocket)
Code4:ClientCnxn的具体实例化
Code5:SendThread的具体实例化
Code6:EventThread的具体实例化
Code 7:SendThread核心run流程
Code 8:startConnect()
Code 9: clientCnxnSocket.connect
Code10:registerAndConnect()
Code11:primeConnection()
Code 12:doTransport()
Code13:findSendablePacket()
Code14:IO write
Code15:createBB()
Code 16:IO read
Code 17: readResponse
Code 18:EventThread run:

源码: Zookeeper 3.4.6.jar(吐血总结)

一、几个重要的类

    1) ZookeeperMain: main函数为入口,由zkCli.sh脚本调用启动
    2)  ZooKeeper:客户端入口
    3)  ZooKeeper.SendThread: IO线程
    4) ZooKeeper.EventThread: 事件处理线程,处理各类消息callback
    5) ClientCnxn: 客户端与服务器端交互的主要类
    6) ClientCnxnSocketNIO:继承自ClientCnxnSocket,专门处理IO, 利用JAVANIO
    7) Watcher: 用于监控Znode节点
    9) WatcherManager:用来管理Watcher,管理了ZK Client绑定的所有Watcher。

二、JAVA的基础知识

1)JAVA多线程
2)JAVANIO:  可参考:http://blog.csdn.net/cnh294141800/article/details/52996819
3)Socket编程(稍微了解即可)
4)JLine: 是一个用来处理控制台输入的Java类库

三、大致了解
这里写图片描述
上图就是对Zookeeper源码一个最好的解释,
(1) Client端发送Request(封装成Packet)请求到Zookeeper
(2) Zookeeper处理Request并将该请求放入Outgoing Queue(顾名思义,外出队列,就是让Zookeeper服务器处理的队列),
(3) Zookeeper端处理Outgoing Queue,并将该事件移到Pending Queue中
(4) Zookeeper端消费Pending Queue,并调用finishPacket(),生成Event
(5) EventThread线程消费Event事件,并且处理Watcher.

四 从入门到放弃的讲解
(1)应用 提供watch实例(new MyWatcher(null))

private class MyWatcher implements Watcher {
     // 默认Watcher 
        public void process(WatchedEvent event) {
            if (getPrintWatches()) {
                ZooKeeperMain.printMessage("WATCHER::");
                ZooKeeperMain.printMessage(event.toString());
            }
        }
    }

(2)实例化zookeeper
 实例化socket,默认使用ClientCnxnSocketNIO
 实例化ClientCnxn
 实例化SendThread
 实例化EventThread
Code1:ZK

zk = new ZooKeeper(host Integer.parseInt(cl.getOption("timeout")),
                 new MyWatcher(), readOnly);   //  初始化ZK

Code2:

public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
            boolean canBeReadOnly)
        throws IOException
    {
        …
        watchManager.defaultWatcher = watcher;    // 设置defaultWatcher 为 MyWatcher
        ConnectStringParser connectStringParser = new ConnectStringParser(
                connectString);   // 解析-server 获取 IP以及PORT
        HostProvider hostProvider = new StaticHostProvider(
                connectStringParser.getServerAddresses());
        cnxn = new ClientCnxn(connectStringParser.getChrootPath(),
                hostProvider, sessionTimeout, this, watchManager,
                getClientCnxnSocket(), canBeReadOnly);  // 创建 ClientCnxn实例

        cnxn.start();   // 启动cnxn中的SendThread and EventThread进程
    }

Code3:实例化ClientCnxnSocketNIO (which extends ClientCnxnSocket)

private static ClientCnxnSocket getClientCnxnSocket() throws IOException {
        String clientCnxnSocketName = System
                .getProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET);
        if (clientCnxnSocketName == null) {
            clientCnxnSocketName = ClientCnxnSocketNIO.class.getName();
        }
        try {
            return (ClientCnxnSocket) Class.forName(clientCnxnSocketName)
                    .newInstance();
        } catch (Exception e) {
            IOException ioe = new IOException("Couldn't instantiate "
                    + clientCnxnSocketName);
            ioe.initCause(e);
            throw ioe;
        }
    }

Code4:ClientCnxn的具体实例化
/* 另一个ClientCnxn构造函数, 可见时sessionId=0

public ClientCnxn(String chrootPath, HostProvider hostProvider, int sessionTimeout, ZooKeeper zooKeeper,
            ClientWatchManager watcher, ClientCnxnSocket clientCnxnSocket, boolean canBeReadOnly)
            throws IOException {
        this(chrootPath, hostProvider, sessionTimeout, zooKeeper, watcher,
             clientCnxnSocket, 0, new byte[16], canBeReadOnly);
}
*/
public ClientCnxn(String chrootPath, HostProvider hostProvider, int sessionTimeout, ZooKeeper zooKeeper,
            ClientWatchManager watcher, ClientCnxnSocket clientCnxnSocket,
            long sessionId, byte[] sessionPasswd, boolean canBeReadOnly) {
        this.zooKeeper = zooKeeper;   
        this.watcher = watcher;
        this.sessionId = sessionId;
        this.sessionPasswd = sessionPasswd;
        this.sessionTimeout = sessionTimeout;
      //主机列表
        this.hostProvider = hostProvider;
        this.chrootPath = chrootPath;
      //连接超时
        connectTimeout = sessionTimeout / hostProvider.size();
      //读超时 
        readTimeout = sessionTimeout * 2 / 3;
        readOnly = canBeReadOnly;
      //初始化client2个核心线程,SendThread是client的IO核心线程,EventThread从SendThread里拿到event
        sendThread = new SendThread(clientCnxnSocket);
        eventThread = new EventThread();

    }

Code5:SendThread的具体实例化

SendThread(ClientCnxnSocket clientCnxnSocket) {
            super(makeThreadName("-SendThread()"));
            state = States.CONNE
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值