Zookeeper源码解析(一):客户端与服务端之间是怎么交互的

本文深入解析ZooKeeper客户端与服务端的交互流程,涵盖客户端和服务端的启动过程,数据交互机制,以及服务端的请求处理链。通过源码分析,揭示ZooKeeper高效稳定运行的秘密。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我的源码链接

github,我已经添加上了很多注释,拉下来就可以直接看。

简单描述

先总述一下,zk的客户端与服务端交互的大概思路。
客户端 一个线程 while循环队列(LinkedList)中取数据发送给服务端或者接受服务端的数据
服务端 同理。

源码入口

客户端:
我们知道在linux中如果想链接zk则要通过zkCli.sh脚本。(这个不知道的请先去熟悉一下zk)

#!/usr/bin/env bash
# use POSTIX interface, symlink is followed automatically
ZOOBIN="${BASH_SOURCE-$0}"
ZOOBIN="$(dirname "${ZOOBIN}")"
ZOOBINDIR="$(cd "${ZOOBIN}"; pwd)"

if [ -e "$ZOOBIN/../libexec/zkEnv.sh" ]; then
  . "$ZOOBINDIR"/../libexec/zkEnv.sh
else
  . "$ZOOBINDIR"/zkEnv.sh
fi

"$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
     -cp "$CLASSPATH" $CLIENT_JVMFLAGS $JVMFLAGS \
     org.apache.zookeeper.ZooKeeperMain "$@"

通过上面的脚本可以知道最终zkCli.sh 就是执行了org.apache.zookeeper.ZooKeeperMain的main方法。

服务端:
同理服务端也是通过zkServer.sh 脚本来启动(由于该脚本有点长。找到核心代码)

ZOOMAIN="org.apache.zookeeper.server.quorum.QuorumPeerMain"
=====================
start)
    echo  -n "Starting zookeeper ... "
    if [ -f "$ZOOPIDFILE" ]; then
      if kill -0 `cat "$ZOOPIDFILE"` > /dev/null 2>&1; then
         echo $command already running as process `cat "$ZOOPIDFILE"`. 
         exit 0
      fi
    fi
    nohup "$JAVA" "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
    if [ $? -eq 0 ]
    then
      case "$OSTYPE" in
      *solaris*)
        /bin/echo "${!}\\c" > "$ZOOPIDFILE"
        ;;
      *)
        /bin/echo -n $! > "$ZOOPIDFILE"
        ;;
      esac
      if [ $? -eq 0 ];
      then
        sleep 1
        echo STARTED
      else
        echo FAILED TO WRITE PID
        exit 1
      fi
    else
      echo SERVER DID NOT START
      exit 1
    fi
    ;;

可以看到最终启动的时候也就是执行了QuorumPeerMain的main方法

客户端启动流程

ZookeeperMain.java

    public static void main(String args[])
        throws KeeperException, IOException, InterruptedException
    {
   
        // 初始化
        // 去建立与服务端的sokcet
        // 开启后台线程,循环从sokcet读、写数据
        ZooKeeperMain main = new ZooKeeperMain(args);

        //监听  后续命令行 命令并处理
        //就是你执行完zkCli.sh后控制台与你交互的命令行,就是在这里执行的。
        main.run();
    }

重点看下 ZooKeeperMain main = new ZooKeeperMain(args)

    public ZooKeeperMain(String args[]) throws IOException, InterruptedException {
   
        // 命令行 参数解析
        cl.parseOptions(args);
        System.out.println("Connecting to " + cl.getOption("server"));
        // 连接服务器,并且初始化zk
        connectToZK(cl.getOption("server"));
        //zk = new ZooKeeper(cl.getOption("server"),
//                Integer.parseInt(cl.getOption("timeout")), new MyWatcher());
    }
 protected void connectToZK(String newHost) throws InterruptedException, IOException {
   
        if (zk != null && zk.getState().isAlive()) {
   
            zk.close();
        }
        host = newHost;
        boolean readOnly = cl.getOption("readonly") != null;
        // 初始化 ZooKeeper 类
        /**
         * 1、getClientCnxnSocket() 准备好一个 Socket连接
         * 2、sendThread = new SendThread(clientCnxnSocket);   发送线程(包括连接、发送数据)
         * 3、eventThread = new EventThread();  事件线程
         * 调用 start方法
         */
        zk = new ZooKeeper(host,
                 Integer.parseInt(cl.getOption("timeout")),
                 new MyWatcher(), readOnly);
    }
    
public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher,
            boolean canBeReadOnly)
        throws IOException
    {
   
        LOG.info("Initiating client connection, connectString=" + connectString
                + " sessionTimeout=" + sessionTimeout + " watcher&
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七层汉堡王

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值