Zookeeper官网Java示例代码解读(一)

news2024/9/22 17:26:54

2024-08-22

1. 基本信息

  • 官网地址:
    https://zookeeper.apache.org/doc/r3.8.4/javaExample.html

  • 示例设计思路

Conventionally, ZooKeeper applications are broken into two units, one which maintains the connection, and the other which monitors data. In this application, the class called the Executor maintains the ZooKeeper connection, and the class called the DataMonitor monitors the data in the ZooKeeper tree. Also, Executor contains the main thread and contains the execution logic. It is responsible for what little user interaction there is, as well as interaction with the executable program you pass in as an argument and which the sample (per the requirements) shuts down and restarts, according to the state of the znode.

  • Demo的功能
    借助Zookeeper实现分布式环境中的配置文件实时更新

2. 环境准备

  • 准备一台虚拟机(也可以在本机启动ZooKeeper)
  • 安装ZooKeeper、JDK
  • 启动ZooKeeper Server
  • 启动客户端,创建znode,用于测试

3. 示例代码

3.1 Executor

package com.agileluo.zookeeperdemo.simple_watch;  
  
/**  
 * A simple example program to use DataMonitor to start and * stop executables based on a znode. The program watches the * specified znode and saves the data that corresponds to the * znode in the filesystem. It also starts the specified program * with the specified arguments when the znode exists and kills * the program if the znode goes away. */import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
  
import org.apache.zookeeper.KeeperException;  
import org.apache.zookeeper.WatchedEvent;  
import org.apache.zookeeper.Watcher;  
import org.apache.zookeeper.ZooKeeper;  
  
public class Executor  
        implements Watcher, Runnable, DataMonitor.DataMonitorListener  
{  
    String znode;  
    DataMonitor dm;  
    ZooKeeper zk;  
    String filename;  
    String exec[];  
    Process child;  
  
    static{  
        System.setProperty("zookeeper.sasl.client", "false");  
    }  
  
    public Executor(String hostPort, String znode, String filename,  
                    String exec[]) throws KeeperException, IOException {  
        this.filename = filename;  
        this.exec = exec;  
        zk = new ZooKeeper(hostPort, 3000, this);  
        dm = new DataMonitor(zk, znode, null, this);  
    }  
  
    /**  
     * @param args  
     */  
    public static void main(String[] args) {  
        if (args.length < 4) {  
            System.err  
                    .println("USAGE: Executor hostPort znode filename program [args ...]");  
            System.exit(2);  
        }  
        String hostPort = args[0];  
        String znode = args[1];  
        String filename = args[2];  
        String exec[] = new String[args.length - 3];  
        System.arraycopy(args, 3, exec, 0, exec.length);  
        try {  
            new Executor(hostPort, znode, filename, exec).run();  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    /***************************************************************************  
     * We do process any events ourselves, we just need to forward them on.     *     * @see org.apache.zookeeper.Watcher #process(org.apache.zookeeper.proto.WatcherEvent)  
     */    public void process(WatchedEvent event) {  
        dm.process(event);  
    }  
  
    public void run() {  
        try {  
            synchronized (this) {  
                while (!dm.dead) {  
                    wait();  
                }  
            }  
        } catch (InterruptedException e) {  
        }  
    }  
  
    public void closing(int rc) {  
        synchronized (this) {  
            notifyAll();  
        }  
    }  
  
    static class StreamWriter extends Thread {  
        OutputStream os;  
  
        InputStream is;  
  
        StreamWriter(InputStream is, OutputStream os) {  
            this.is = is;  
            this.os = os;  
            start();  
        }  
  
        public void run() {  
            byte b[] = new byte[80];  
            int rc;  
            try {  
                while ((rc = is.read(b)) > 0) {  
                    os.write(b, 0, rc);  
                }  
            } catch (IOException e) {  
            }  
  
        }  
    }  
  
    /**  
     * DataMonitor.DataMonitorListener 接口方法exists()的实现  
     * @param data  
     */  
    public void exists(byte[] data) {  
        if (data == null) { //zooKeeper客户端操作(delete /my_test)时触发  
            if (child != null) {  
                System.out.println("Killing process");  
                child.destroy();  
                try {  
                    child.waitFor();  
                } catch (InterruptedException e) {  
                }  
            }  
            child = null;  
        } else {  //zooKeeper客户端操作(set /my_test test_data)时触发  
            if (child != null) {  
                System.out.println("Stopping child");  
                child.destroy();  
                try {  
                    child.waitFor();  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                }  
            }  
            try { //将变化的配置写入文件,默认路径为项目源文件的根目录  
                FileOutputStream fos = new FileOutputStream(filename);  
                fos.write(data);  
                fos.close();  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
            try {  
                System.out.println("Starting child");  
                //从控制台读取命令行,并执行命令  
                child = Runtime.getRuntime().exec(exec);  
                new StreamWriter(child.getInputStream(), System.out);  
                new StreamWriter(child.getErrorStream(), System.err);  
            } catch (IOException e) {  
                e.printStackTrace();  
            }  
        }  
    }  
}

3.2 DataMonitor

package com.agileluo.zookeeperdemo.simple_watch;  
  
/**  
 * A simple class that monitors the data and existence of a ZooKeeper * node. It uses asynchronous ZooKeeper APIs. */import java.util.Arrays;  
  
import org.apache.zookeeper.KeeperException;  
import org.apache.zookeeper.WatchedEvent;  
import org.apache.zookeeper.Watcher;  
import org.apache.zookeeper.ZooKeeper;  
import org.apache.zookeeper.AsyncCallback.StatCallback;  
import org.apache.zookeeper.KeeperException.Code;  
import org.apache.zookeeper.data.Stat;  
  
public class DataMonitor implements Watcher, StatCallback {  
  
    ZooKeeper zk;  
    String znode;  
    Watcher chainedWatcher;  
    boolean dead;  
    DataMonitorListener listener;  
    byte prevData[];  
  
    public DataMonitor(ZooKeeper zk, String znode, Watcher chainedWatcher,  
                       DataMonitorListener listener) {  
        this.zk = zk;  
        this.znode = znode;  
        this.chainedWatcher = chainedWatcher;  
        this.listener = listener;  
        // Get things started by checking if the node exists. We are going  
        // to be completely event driven        zk.exists(znode, true, this, null);  
    }  
  
    /**  
     * Other classes use the DataMonitor by implementing this method     */    public interface DataMonitorListener {  
        /**  
         * The existence status of the node has changed.         */        void exists(byte data[]);  
  
        /**  
         * The ZooKeeper session is no longer valid.         *         * @param rc  
         *                the ZooKeeper reason code  
         */        void closing(int rc);  
    }  
  
    public void process(WatchedEvent event) {  
        String path = event.getPath();  
        if (event.getType() == Event.EventType.None) {  
            // We are are being told that the state of the  
            // connection has changed            switch (event.getState()) {  
                case SyncConnected:  
                    // In this particular example we don't need to do anything  
                    // here - watches are automatically re-registered with                    // server and any watches triggered while the client was                    // disconnected will be delivered (in order of course)                    break;  
                case Expired:  
                    // It's all over  
                    dead = true;  
                    listener.closing(KeeperException.Code.SessionExpired);  
                    break;  
            }  
        } else {  
            if (path != null && path.equals(znode)) {  
                // Something has changed on the node, let's find out  
                zk.exists(znode, true, this, null);  
            }  
        }  
        if (chainedWatcher != null) {  
            chainedWatcher.process(event);  
        }  
    }  
  
    public void processResult(int rc, String path, Object ctx, Stat stat) {  
        boolean exists;  
        switch (rc) {  
            case Code.Ok:  
                exists = true;  
                break;  
            case Code.NoNode:  
                exists = false;  
                break;  
            case Code.SessionExpired:  
            case Code.NoAuth:  
                dead = true;  
                listener.closing(rc);  
                return;  
            default:  
                // Retry errors  
                zk.exists(znode, true, this, null);  
                return;  
        }  
  
        byte b[] = null;  
        if (exists) {  
            try {  
                b = zk.getData(znode, false, null);  
            } catch (KeeperException e) {  
                // We don't need to worry about recovering now. The watch  
                // callbacks will kick off any exception handling                e.printStackTrace();  
            } catch (InterruptedException e) {  
                return;  
            }  
        }  
        if ((b == null && b != prevData)  
                || (b != null && !Arrays.equals(prevData, b))) {  
            listener.exists(b);  
            prevData = b;  
        }  
    }  
}

4. 测试

运行Executor,参数传入: 192.168.206.100:2181 /my_test filename calc

其中192.168.206.100:2181为ZooKeeper的访问串;
/my_test 是预先创建的Znode
filename 是变动的Znode数据写入的文件,只保留最后的数据,
calc 指定执行完成后,此例为打开计算器(因为是在Windows下跑,所以可以有cmd,run,calc可以用来做测试)

5 注意点

5.1 防火墙

查看防火墙的状态
systemctl status firewalld.service

 firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Tue 2024-08-27 19:41:00 PDT; 2s ago
     Docs: man:firewalld(1)
 Main PID: 2967 (firewalld)
    Tasks: 2
   CGroup: /system.slice/firewalld.service
           └─2967 /usr/bin/python2 -Es /usr/sbin/firewalld --nofork --nopid

关闭/开启VM的防火墙
systemctl stop|start firewalld.service

5.2 关闭SASL安全验证

Executor类中增加代码:

static{  
    System.setProperty("zookeeper.sasl.client", "false");  
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2086155.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

昇思AI框架实践2:基于T5的SQL语句生成模型推理

MindSpore 基于T5的SQL语句生成项目实施 基于T5的SQL语句生成项目介绍 本项目旨在开发一个基于T5-small模型的自然语言转SQL语句生成器。该生成器能够将用户以自然语言形式提出的查询请求转换为对应的SQL查询语句&#xff0c;从而使得即使是不熟悉SQL语言的用户也能够轻松地从…

【Java EE】JVM

目录 1. JVM简介 2.JVM运行流程 3.JVM运行时数据区 3.1 堆&#xff08;线程共享&#xff09; 3.2 Java虚拟机栈&#xff08;线程私有&#xff09; 1. JVM简介 JVM是 Java Virtual Machine 的简称&#xff0c;意为Java虚拟机。 虚拟机是指通过软件模拟的具有完整硬件功能的…

马克·古尔曼:预计苹果新款Macs要到10月才会发布

马克古尔曼当地时间8月24日在社交媒体平台推特平台发文称&#xff0c;从以往模式来看&#xff0c;预计苹果公司新款Mac要到10月才会发布。 古尔曼称&#xff0c;预计Mac mini将是今年最值得关注的、配置M4芯片的Mac&#xff0c;但预计苹果还会发布新款MacBook Pro。他表示&…

【Qt】网格布局管理器QGridLayout

网格布局管理器QGridLayout Qt中提供QGridLayout用来实现网格布局的效果。 核心属性 整体和 QVBoxLayout 以及 QHBoxLayout 相似. 但是设置 spacing 的时候是按照垂直⽔平两个 ⽅向来设置的. 属性说明 layoutLeftMargin 左侧边距 layoutRightMargin 右侧边距 layoutTo…

类与Object.create之间的继承

前言 ● 下面是一段之前学习Object.create的一段代码 const PersonProto {calcAge() {console.log(2037 - this.birthYear);},init(firstName, birthYear) {this.firstName firstName;this.birthYear birthYear;} };const zhangsan Object.create(PersonProto); ● 和之前…

day-43 括号生成

思路 通过深度优先遍历&#xff0c;把所有可能的组合枚举出来&#xff0c;然后依次判断是否符合括号规则&#xff0c;符合则加入链表 解题过程 判断是否括号规则&#xff1a;第一个位置只能是(&#xff0c;维护一个val值(初始值为0)&#xff0c;遍历字符串&#xff0c;每当加入…

深度强化学习算法(四)(附带MATLAB程序)

深度强化学习&#xff08;Deep Reinforcement Learning, DRL&#xff09;结合了深度学习和强化学习的优点&#xff0c;能够处理具有高维状态和动作空间的复杂任务。它的核心思想是利用深度神经网络来逼近强化学习中的策略函数和价值函数&#xff0c;从而提高学习能力和决策效率…

【项目日记】高并发内存池---实现线程缓存

比起那些用大嗓门企图压制世界的人&#xff0c; 让全世界都安静下来听你小声说话的人更可畏。 --- 韩寒 《告白与告别》--- 高并发内存池项目---实现线程缓存 1 框架设计2 自由链表类和哈希规则2.1 自由链表类2.2 映射规则 3 实现线程缓存3.1 申请内存3.2 释放内存 4 多线程…

day-43 盛最多水的容器

思路 双指针&#xff1a;首先令i0,jheight.length-1,选取短板&#xff08;即Math.min(height[i],height[j])&#xff09;,然后将短板向内移动&#xff0c;直达i>j即可得到答案。 解题过程 短板向内移动&#xff1a;水的容量可能增大 长板向内移动&#xff1a;水的容量不可能…

树莓派5安装系统并配置SSH与VNC权限实现Windows设备远程连接

文章目录 前言1. 使用 Raspberry Pi Imager 安装 Raspberry Pi OS2. Windows安装VNC远程树莓派3. 使用VNC Viewer公网远程访问树莓派3.1 安装Cpolar步骤3.2 配置固定的公网地址3.3 VNC远程连接测试 4. 固定远程连接公网地址4.1 固定TCP地址测试 前言 本文主要介绍如何在树莓派…

数字化转型升级探索(一)

在数字化转型升级的探索中&#xff0c;我们将通过实施综合数字化战略&#xff0c;涵盖从前端用户体验优化到后端系统集成的全方位提升&#xff0c;利用大数据、人工智能、云计算等先进技术对业务流程进行智能化改造&#xff0c;推进自动化和数据驱动决策&#xff0c;推动业务模…

VMware安装Ubuntu 23.10.1系统图文版

文章目录 Ubuntu系统介绍引言Ubuntu系统的特点1. 开源免费2. 易用性3. 稳定性与安全性4. 强大的社区支持 安装与初步设置下载ISO镜像安装1.新建虚拟机2.选择“自定义(高级)”&#xff0c;并点击【下一步】3.选择虚拟机硬件兼容性(默认就好)&#xff0c;并点击【下一步】4.选择“…

爆改yolov8|利用BSAM改进YOLOv8,高效涨点

1&#xff0c;本文介绍 BSAM基于CBAM进行改进&#xff0c;经实测在多个数据集上都有涨点。 BSAM&#xff08;BiLevel Spatial Attention Module&#xff09;是一个用于提升深度学习模型在空间特征处理中的能力的模块。它主要通过双层注意力机制来增强模型对重要空间信息的关注…

一款支持固定区域,固定尺寸大小重复截图的软件

WinSnap是一款功能强大的屏幕截图软件&#xff0c;可以实现对固定区域&#xff0c;固定尺寸大小区域重复截图&#xff0c;适用于日常截图需求和专业用户进行屏幕截图和图像编辑。通过设置快捷键&#xff0c;方便快速重复截图固定区域固定大小。它支持捕捉整个屏幕、活动窗口、选…

H264码流结构讲解

所谓的码流结构就是指&#xff1a;视频经过编码之后所得到的数据是怎样排列的&#xff0c;换句话说&#xff0c;就是编码后的码流我们该如何将一帧一帧的数据分离开来&#xff0c;哪一块数据是一帧图像&#xff0c;哪一块是另外一帧图像&#xff0c;只要了解了这个&#xff0c;…

UE开发中的设计模式(四) —— 组合模式

面试中被面试官问到组合模式和继承有什么区别&#xff0c;给我问懵了&#xff0c;今天又仔细看了下&#xff0c;这不就是UE里的组件吗 >_< 文章目录 问题提出概述问题解决总结组合模式的优缺点继承的优缺点 问题提出 考虑这样一个场景&#xff0c;我们有一个敌人的基类&…

【读书笔记-《30天自制操作系统》-10】Day11

本篇内容继续围绕显示展开。首先对鼠标显示做了些优化&#xff0c;鼠标箭头在到达画面边缘时能够实现部分隐藏&#xff1b;接下来制作了窗口&#xff0c;实现了窗口显示&#xff1b;最后还在窗口的基础上实现了计数器&#xff0c;显示计数的变化并消除闪烁的问题。 1. 画面边…

Java 6.3 - 定时任务

为什么需要定时任务&#xff1f; 常见业务场景&#xff1a; 1、支付10min失效 2、某系统凌晨进行数据备份 3、视频网站定时发布视频 4、媒体聚合平台每10min抓取某网站数据为己用 …… 这些场景需要我们在某个特定时间去做某些事情。 单机定时任务技术有哪些&#xff1f…

form-data和x-www-form-urlencoded的区别

form-data和x-www-form-urlencoded区别 form-data 和 x-www-form-urlencoded 都是表单请求的一种格式&#xff0c;主要区别有两点。 编码方式不同 我们先说x-www-form-urlencoded&#xff0c;它的编码方式就隐藏在名字里&#xff1a;urlencoded。看到这个关键词&#xff0c;…