Java教程

调试 ZooKeeper 源码

本文主要是介绍调试 ZooKeeper 源码,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

首先将源码 clone 下来:

➜  gitee git clone https://github.com/apache/zookeeper.git

导入到 IDEA 中:

单机模式

拷贝配置文件

可以将 conf/zoo_sample.cfg 复制到自定义目录。这里直接拷贝到当前conf目录下,并命名为 zoo1.cfg:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/Users/dongguabai/Desktop/temp/zookeeper/z1/data
dataLogDir=/Users/dongguabai/Desktop/temp/zookeeper/z1/log
clientPort=2181

拷贝 log4j.properties

在 conf/log4j.properties 的日志配置拷贝一份到 zookeeper/zookeeper-server/src/main/resources 。这样才能打印出更多的日志提供调试。

注意还要将 zookeeper-server/src/main/resources 标记为资源目录,否则日志会不生效。

寻找 ZooKeeper Server 的启动主类

我们都知道,ZooKeeper 平时是使用 zkServer.sh 启动的。查看一下这个 shell 脚本:

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 1
      fi
    fi
    nohup "$JAVA" $ZOO_DATADIR_AUTOCREATE "-Dzookeeper.log.dir=${ZOO_LOG_DIR}" \
    "-Dzookeeper.log.file=${ZOO_LOG_FILE}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}" \
    -XX:+HeapDumpOnOutOfMemoryError -XX:OnOutOfMemoryError='kill -9 %p' \
    -cp "$CLASSPATH" $JVMFLAGS $ZOOMAIN 这里标记着 ZOOMAIN 方法 "$ZOOCFG" > "$_ZOO_DAEMON_OUT" 2>&1 < /dev/null &
    
    ZOOMAIN ZOOCFG 为参数
    .... 
    
    ZOOMAIN="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.local.only
        =$JMXLOCALONLY org.apache.zookeeper.server.quorum.QuorumPeerMain"
    
    从此处可以知道,QuorumPeerMain 类就是 ZooKeeper Server 的启动类了。 
  

从 shell 文件中看到,QuorumPeerMain 类就是 ZooKeeper Server 的启动类了。

配置启动参数:

编译处理

zookeeper-jute 需要 mvn compile 生成,IDEA 可能不会自动导入,可以编译一些:

还可能会出现很多编译报错,直接 install 一下:

mvn clean install -DskipTests

还有的可能需要添加一些依赖:

编译问题处理后,直接 debug 走起:

可以发现已经启动成功了。

测试

测试一波:

package dongguabai.zookeeper;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;

import java.util.concurrent.CountDownLatch;

import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;

import java.util.concurrent.CountDownLatch;
/**
 * @author Dongguabai
 * @description
 * @date 2021-04-23 13:53
 */
public class OriginalZkTest {

    //static final String CONNECT_ADDR = "172.16.140.131:2181,172.16.140.131:2181,172.16.140.131:2181";
    static final String CONNECT_ADDR = "localhost:2181";

    static final int SESSION_OUTTIME = 2000;//ms

    static final CountDownLatch connectedSemaphore = new CountDownLatch(1);

    public static void main(String[] args) throws Exception {

        ZooKeeper zk = new ZooKeeper(CONNECT_ADDR, SESSION_OUTTIME, new Watcher() {
            public void process(WatchedEvent event) {
                KeeperState keeperState = event.getState();
                EventType eventType = event.getType();
                if (KeeperState.SyncConnected == keeperState) {
                    if (EventType.None == eventType) {
                        connectedSemaphore.countDown();
                        System.out.println("zk connected");
                    }
                }
            }
        });

        connectedSemaphore.await();

        String s = zk.create("/testRoot1", "testRoot1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
        System.out.println(s);

        System.out.println("connected..");
        zk.close();

    }
}

输出:

zk connected
/testRoot1
connected..

查看节点是否创建了:

➜  bin sh zkServer.sh -server localhost:2181
[zk: localhost:2181(CONNECTED) 0] ls /
[testRoot1, zookeeper]

可以发现单机版启动成功。

集群模式

首先在之前的 conf 目录中增加3个配置文件,名字分别为zoo1.cfgzoo2.cfgzoo3.cfg:

zoo1.cfg:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/Users/dongguabai/Desktop/temp/zookeeper/z1/data
dataLogDir=/Users/dongguabai/Desktop/temp/zookeeper/z1/log
# 客户端连接的端口
clientPort=2181

server.1=127.0.0.1:2887:3887
server.2=127.0.0.1:2888:3888
server.3=127.0.0.1:2889:3889

zoo2.cfg:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/Users/dongguabai/Desktop/temp/zookeeper/z2/data
dataLogDir=/Users/dongguabai/Desktop/temp/zookeeper/z2/log
clientPort=2182

server.1=127.0.0.1:2887:3887
server.2=127.0.0.1:2888:3888
server.3=127.0.0.1:2889:3889

zoo3.cfg:

tickTime=2000
initLimit=10
syncLimit=5
dataDir=/Users/dongguabai/Desktop/temp/zookeeper/z3/data
dataLogDir=/Users/dongguabai/Desktop/temp/zookeeper/z3/log
clientPort=2183

server.1=127.0.0.1:2887:3887
server.2=127.0.0.1:2888:3888
server.3=127.0.0.1:2889:3889

当然,相关的目录也要建好:

接下来配置 myid 文件,ZK 在集群模式下运行时会读取位于 dataDir 目录下的 myid 文件:

内容分别为 1、2、3。

接下来多配置几个启动器:

分别运行一下试试:

查看各个节点的状态:

➜  bin telnet localhost 2181
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stat
Zookeeper version: 3.8.0-SNAPSHOT-1590a424cb7a8768b0ae01f2957856b1834dd68d-dirty, built on 2021-04-23 10:09 UTC
Clients:
 /0:0:0:0:0:0:0:1:62163[0](queued=0,recved=1,sent=0)
 /127.0.0.1:62157[1](queued=0,recved=2,sent=2)

Latency min/avg/max: 3/3.0/3
Received: 3
Sent: 2
Connections: 2
Outstanding: 0
Zxid: 0x100000006
Mode: follower
Node count: 6
Connection closed by foreign host.
➜  bin telnet localhost 2182
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stat
Zookeeper version: 3.8.0-SNAPSHOT-1590a424cb7a8768b0ae01f2957856b1834dd68d-dirty, built on 2021-04-23 10:09 UTC
Clients:
 /127.0.0.1:62154[1](queued=0,recved=10,sent=10)
 /0:0:0:0:0:0:0:1:62204[0](queued=0,recved=1,sent=0)

Latency min/avg/max: 0/1.2222/4
Received: 11
Sent: 10
Connections: 2
Outstanding: 0
Zxid: 0x200000000
Mode: leader
Node count: 6
Proposal sizes last/min/max: -1/-1/-1
Connection closed by foreign host.
➜  bin telnet localhost 2183
Trying ::1...
Connected to localhost.
Escape character is '^]'.
stat
Zookeeper version: 3.8.0-SNAPSHOT-1590a424cb7a8768b0ae01f2957856b1834dd68d-dirty, built on 2021-04-23 10:09 UTC
Clients:
 /0:0:0:0:0:0:0:1:62206[0](queued=0,recved=1,sent=0)
 /0:0:0:0:0:0:0:1:62162[1](queued=0,recved=12,sent=12)

Latency min/avg/max: 0/0.5455/2
Received: 13
Sent: 12
Connections: 2
Outstanding: 0
Zxid: 0x100000006
Mode: follower
Node count: 6
Connection closed by foreign host.

当然也可以客户端访问:

至此 ZK 集群已经搭建完毕!

References

  • https://juejin.cn/post/6844904151772561416

 

这篇关于调试 ZooKeeper 源码的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!