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

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 daemonLoaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)Active: active (running) since Tue 2024-08-27 19:41:00 PDT; 2s agoDocs: man:firewalld(1)Main PID: 2967 (firewalld)Tasks: 2CGroup: /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.rhkb.cn/news/412126.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在随机点实现凸包包围游戏地区

讲解视频在连接点之后&#xff0c;想起来两年前看数学书&#xff0c;记住凸包二字&#xff0c;连接敌人外围点&#xff0c;意外找到凸包算法_哔哩哔哩_bilibili //author bilibili 民用级脑的研发记录 // 开发环境 小熊猫c 2.25.1 raylib 版本 4.5 // 2024-7-14 // AABB 碰撞…

USB3202N多功能数据采集卡16位模拟量250K频率LabVIEW采集卡

品牌&#xff1a;阿尔泰科技 系列&#xff1a;多功能数据采集卡 概述&#xff1a; USB3202N多功能数据采集卡&#xff0c;LabVIEW无缝连接&#xff0c;提供图形化API函数&#xff0c;提供8通道&#xff08;RSE、NRSE&#xff09;、4通道&#xff08;DIFF&#xff09;模拟量输…

《HelloGitHub》第 101 期

兴趣是最好的老师&#xff0c;HelloGitHub 让你对编程感兴趣&#xff01; 简介 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。 github.com/521xueweihan/HelloGitHub 这里有实战项目、入门教程、黑科技、开源书籍、大厂开源项目等&#xff0c;涵盖多种编程语言 Python、…

DataWhale AI夏令营 2024大运河杯-数据开发应用创新赛-task2

DataWhale AI夏令营 2024大运河杯-数据开发应用创新赛 YOLO(You Only Look Once)上分心得分享 YOLO(You Only Look Once) YOLO算的上是近几年最火的目标检测模型了&#xff0c;被广泛的应用在工业、学术等领域。 YOLOv1&#xff08;You Only Look Once 第一版&#xff09;于 2…

CTFHub SSRF靶场通关攻略

内网访问 首先进入环境 在url后面输入 http://127.0.0.1/flag.php访问&#xff0c;得出flag 伪协议读取文件 进入环境后再url后面拼接 file:///var/www/html/flag.php 访问后是&#xff1f;&#xff1f;&#xff1f;&#xff0c;那么我们F12检查源码得出flag 端口扫描 我们进行…

若依微服务ruoyi-auth在knife4j中不显示问题解决

关于若依微服务ruoyi-auth在knife4j中不显示问题解决 解决办法 一、添加swagger依赖文件 在ruoyi-auth模块下的pom.xml文件中添加ruoyi-common-swagger依赖 <!-- RuoYi Common Swagger --><dependency><groupId>com.ruoy

Python网络爬虫模拟登录与验证解析

内容导读 使用Selenium模拟登录 使用Cookies登录网站 模拟表单登录网站 爬虫识别简单的验证码 实例解析 一、使用Selenium模拟登录 1、为什么要模拟登录 在互联网上存在大量需要登录才能访问的网站&#xff0c;要爬取这些网站&#xff0c;就需要学习爬虫的模拟登录。对…

裸机:SD卡启动详解

内存和外存的区别 内存和外存在计算机系统中扮演着不同的角色&#xff0c;它们之间存在显著的差异。以下是内存和外存之间几个主要方面的区别&#xff1a; 存储特性与易失性 内存&#xff08;Memory&#xff09;&#xff1a;通常指的是随机存取存储器&#xff08;RAM&#x…

Linux实现异步IO的方法:epoll,posix aio,libaio,io_uring

Linux中异步IO的实现方式大概有以下几种&#xff1a; 1. epoll 熟悉网络编程的人可能会想到select&#xff0c;poll&#xff0c;epoll这些异步IO的方式&#xff0c;但实际上这些方式叫做非阻塞IO&#xff0c;并不是实际意义上的异步IO。因此这些只能用于异步的Socket IO&…

【STM32】一些外设通用内容

在学习各种外设的过程中&#xff0c;发现外设有一些通用的东西可以总结一下&#xff0c;后面发现再继续更新。图来源于正点原子的学习视频和PPT。 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 外设的时钟的开启 2 外设初始化的回调机制 3 外设的…

【HuggingFace Transformers】LlamaDecoderLayer源码解析

LlamaDecoderLayer源码解析 1. LlamaDecoderLayer 介绍2. LlamaDecoderLayer 类源码解析 1. LlamaDecoderLayer 介绍 LlamaDecoderLayer 是 LLaMA 模型中的一个关键组件&#xff0c;它结合了自注意力机制、全连接层和残差连接&#xff0c;以及对输入数据的归一化。主要流程为&…

使用 树莓派3B+ 对日本葡萄园进行经济实惠的环境监测

对于 菊岛邦夫—Vineyard Kikushima 而言&#xff0c;Raspberry Pi 生态系统提供了支持和信息&#xff0c;通过基于温度和湿度监测的有针对性的最低限度杀虫剂方案&#xff0c;来提高葡萄的健康产量。 Vineyard Kikushima&#xff1a;http://vykikushima.greater.jp/vineyards…

Ps:工具预设面板

Ps菜单&#xff1a;窗口/工具预设 Window/Tool Presets 工具预设 Tool Presets面板可以为 Photoshop 的图像编辑工作带来极大的便利。 定义好相关的工具预设后&#xff0c;可以直接调用&#xff0c;而不管现在处于什么工具或什么样的参数状态&#xff0c;省去了再次设置参数的麻…

Spring Boot简介与体系知识导图

Spring Boot是Spring开源组织下的一个子项目&#xff0c;是一个基于Spring框架的快速开发脚手架&#xff0c;它极大地简化了Spring应用的初始化和搭建过程&#xff0c;为开发者提供了快速、简单的方式来开发、部署和管理Spring应用。以下是关于Spring Boot的详细介绍&#xff1…

【MRI基础】对比度噪声比CNR概念

​ CNR代表 MRI 中的对比度噪声比。它是通过测量不同组织或感兴趣区域 (ROI) 相对于背景噪声的对比度来评估 MRI 图像质量的指标。更高的 CNR 表示更好的图像质量&#xff0c;因为它表示被比较的区域之间的区别更清晰。 CNR&#xff0c;contrast to noise ratio 基本概念 对比…

【数据结构】-----哈希

目录 一、哈希表概念 二、哈希函数 三、哈希冲突 Ⅰ、定义 Ⅱ、解决 ①闭散列--开放定址法 线性探测 二次线性探测 ②开散列--链地址法&#xff08;哈希桶&#xff09; 问题&#xff1a;哈希表何时扩容&#xff1f; 一、哈希表概念 哈希表又称散列表&#xff0c;它是一…

暄桐教室分享“闲人”指南

一种理想的生活状态&#xff0c;叫“做个闲人”&#xff0c;如苏东坡《行香子述怀》那般&#xff0c;“对一张琴&#xff0c;一壶酒&#xff0c;一溪云”&#xff0c;放下纷扰&#xff0c;好自在。然而&#xff0c;闲并不是简单的无事可做&#xff0c;让自己时光充沛、能量聚集…

【JavaEE初阶】HTTP请求(Request)

&#x1f4d5;引言 HTTP 请求报文由请求行、请求头部、空行 和 请求包体 4 个部分组成 本片文章将从以下四个方面对HTTP请求报文进行解析 URL方法请求报头正文 &#x1f384;认识URL 我们先抓一个包来看一下URL在包里面的位置 平时我们俗称的 “网址” 其实就是说的 URL (…

SVN提取子目录到新库(附带提交历史)方法

plan-A: 以下命令需要直接在服务器上操作&#xff1a; 1、转存test_repo仓库 svnadmin dump test_repo > test_repo.dump 2、筛选指定子目录 svndumpfilter --drop-all-empty-revs include test_dir <test_repo.dump> test_repo_test_dir.dump --drop-all-empty…

MacOS通过Docker部署安装zookeeper、dubbo-admin,以及Docker Desktop进行管理

1.建立一个网络桥接zk docker network create -d bridge zk我们通过docker安装dubbo-admin和zookeeper,为了保证他们能够正常通信,需要使用同一个网络 2.创建zookeeper的docker卷 docker volume create zookeeper_data 3.启动zookeeper,并指定网络和卷 docker run -d \--n…