在debug模式下(没有关闭jvm),创建的临时节点不见了,为什么呢?

背景

使用curator框架作为zookeeper的客户端时,使用debug模式,创建的临时节点过一会就不见了。
pom.xml依赖如下:

        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>4.0.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.zookeeper</groupId>
                    <artifactId>zookeeper</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
            <version>3.4.8</version>
        </dependency>

调用代码如下

    public void createNode(CreateMode mode, String path, String data) throws Exception {
        //curator api 喜欢流式用法(链式调用)  curator:管理者
        RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
        CuratorFramework client = CuratorFrameworkFactory.newClient(zkInfo, retryPolicy);
        //启动客户端
        client.start();
        String result = client.create().withMode(mode).forPath(path, data.getBytes());
        //此处debug
        logger.info(result);

    }

	//调用上方定义的创建节点方法
    crudService.createNode(CreateMode.EPHEMERAL_SEQUENTIAL, "/test", "/test");

logger.info(result);处进行debug,不一会儿,临时节点就不见了。

原因

zookeeper客户端通过sdk连接到zookeeper集群后,会维护一个心跳检测机制(守护线程),每隔一段时间向服务器发送心跳请求,如果太长时间没有发送心跳请求,就会认为客户端断开了连接,那么创建的临时节点就会被删除。

在debug模式下,cpu执行到logger.info(result);这行代码时,会“卡住”。守护线程的心跳请求无法发出,自然而然服务器会剔除掉临时节点。

为了验证我的猜想,我特意做了个测试用例

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                try {
                    for (int i = 0; i < 10000000; i++) {

                    }
                    System.out.println("睡眠2s");
                    logger.info("睡眠2s");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        ExecutorService service = Executors.newFixedThreadPool(1000);
        for (int i = 0; i < 1000; i++) {
            service.submit(thread);
        }

        //thread.setDaemon(true);
        //thread.start();
        //此处debug断点
        System.out.println();

发现当cpu执行到断点处后,不再有日志打印。心跳检测的核心类为org.apache.zookeeper.ClientCnxn,这个类负责着客户端的 socket i/o,维护了一个可用服务端的列表,可以透明自然地切换到它应该连接到的服务端。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐