ZooKeeper官方Java例子解读

博主:爱码叔
个人博客站点: icodebook
公众号:爱码叔漫画软件设计(搜:爱码叔)

专注于软件设计与架构、技术管理。擅长用通俗易懂的语言讲解技术。对技术管理工作有自己的一定见解。文章会第一时间首发在个站上,欢迎大家关注访问!

ZooKeeper官方提供了一个Java监听的例子,本文是我对该例子的学习笔记。可以做为帮助理解此例子的资料:

文档原文连接:ZooKeeper: Because Coordinating Distributed Systems is a Zoo

翻译连接:ZooKeeper官方文档-Java客户端开发例子翻译_爱码叔(稀有气体)的博客-优快云博客

需求理解

我们先回顾一下例子的需求,此客户端有如下四个需求:

1、它接收如下参数:

  • ZooKeeper服务的地址
  • 被监控的znode的名称
  • 可执行命令参数

2、它会取得znode上关联的数据,然后执行命令

3、如果znode变化,客户端重新拉取数据,再次执行命令

4、如果znode消失了,客户端杀掉进行的执行命令

如果你已经学习过或者了解过该例子文档的内容,你应该知道该程序做的事情就是接受用户输入的系统命令,然后监控zookeeper的znode,一旦znode存在,或者发生了变化,程序会把znode最新的数据存入文件,然后起一个线程执行用户的命令,同时还会起两个线程输出执行结果及日志。

举例类比

为了帮助理解,这里举个现实的例子--警察抓坏人:

公安成立了一个行动组准备在嫌疑人住所进行抓捕,警方人员安排如下:

  1. 组长A负责总指挥
  2. 警察B负责监控嫌疑人,并与组长A联络
  3. 警察C,D,E,F埋伏在嫌疑人住所前后左右,准备实施抓捕

整个抓捕过程是这样的:

  1. 组长A下达命令安排后,B,C各就各位(对象A做初始化工作)
  2. B开始监控嫌疑人,一旦嫌疑人进入警察布下的埋伏圈,则马上通知组长A(对象B为watcher,嫌疑人为被监听的znode。A注册为B的listener,在B的监听回调中被触发)
  3. 组长A得到通知后,马上命令C、D、E、F执行抓捕。(C,D,E是被A调用干活的线程)

理解了上线的例子,我们继续对程序进行讲解。

Executor和DataMonitor

本例中有两个主要类,职能如下:

Executor,它是程序的入口。负责初始化zookeeper、DataMonitor,把自己注册为DataMonitor的监听者,一旦DataMonitor监听到变化后,会通知它执行业务操作。

他是例子中的组长A,它有几个内部类是前面说的警员C、D、E、F,负责干活。

DataMonitor,他负责监控znode,发现znode变化后,通知listener执行业务逻辑,同时再次监控znode:

他是例子中的警察B,负责监控犯人,并通知A。

通过以上讲解,这两个主要类所负责的工作应该已经可以充分的理解了。接下来我们针对这两个类进入更为详细的讲解。

内部类和接口:

Executor:

        StreamWriter。继承Thread,以多线程的形式负责把执行的结果输出。相当于例子中的警察C、D、E、F

DataMonitor:

        DataMonitorListener。DataMonitor一旦监控到znode的变化,立即调用自己持有的listener(实现此接口的对象)的exists方法(通知它的监听者)。

继承关系:

Executor:

  • 实现watcher:
    • 监听zookeeper连接的变化,实现process()方法,把事件传递给DataMonitor处理。 
  • 实现DataMonitor中定义的接口DataListener:
    • 实现exists()方法,处理znode变化的具体逻辑。
  • 实现runnable类:
    • run()方法中阻塞主线程,让程序转为事件驱动。
public class Executor implements Watcher, Runnable, DataMonitor.DataMonitorListener{}

DataMonitor:

  • 实现watcher:
    • 监听znode变化。实现process()方法,通过zk.exist()方法再次监听,再次设置自己为zookeeper.exist()的回调(实现不断监听,事件驱动)。同时数据返回后,立即进入下面的回调函数处理
  • 实现StatCallback:
    • 这是zookeeper.exist()操作回调对象。实现processResult()方法,调用DataMonitor持有的listener(也就是Excutor)的exists()方法执行逻辑。
public class DataMonitor implements Watcher, StatCallback{} 

引用关系:

Executor:

  • DataMonitor dm;
  • ZooKeeper zk; //ZooKeeper的连接
  • Process child; //真正执行系统命令的子线程,相当于警察C,D,E,F之一。

DataMonitor:

  • ZooKeeper zk; //和Executor是同一个引用。Executor通过构造函数传入
  • DataMonitorListener listener; //executor对象,Executor通过构造函数传入自己

图解

Executor和DataMonitor的关系如下:

两者通过Executor作为主入口,初始化DataMonitor和ZooKeeper对象后,阻塞主线程。转为事件驱动。即通过DataMonitor监控znode上的事件来驱动程序逻辑。

整个流程如下:

  1. Excutor把自己注册为DataMonitor的监听
  2. DataMonitor实现watcher接口,并监听znode
  3. znode变化时,触发DataMonitor的监听回调
  4. 回调中通过ZooKeeper.exist() 再次监听znode
  5. 上一步exist的回调方法中,调用监听自己的Executor,执行业务逻辑6
  6. Executor启新的线程执行命令
  7. Executor启新的线程打印执行命令的输出

<think>嗯,用户让我解读这个命令:sudo chown -R $USER:$USER /opt/zookeeper。首先,我需要分解这个命令的每个部分,然后解释它们的作用。 首先,sudo 是用来获取管理员权限的,因为更改文件所有权通常需要root权限。接下来是chown,这个命令是change owner的缩写,用来改变文件或目录的所有者。-R选项表示递归处理,也就是不仅改变指定目录本身,还包括其下的所有子目录和文件。然后是$USER:$USER,这里用了环境变量$USER,代表当前登录的用户名,所以前半部分是设置所有者,后半部分是设置所属组。最后的路径/opt/zookeeper是要修改的目标目录。 用户可能是在安装或配置ZooKeeper时遇到了权限问题,导致无法访问或修改相关文件。他们可能不太清楚如何正确设置权限,或者之前使用过root用户操作导致文件归属有问题。这时候需要确保ZooKeeper目录的所有权和权限正确,以便当前用户能够顺利操作,避免权限错误。 另外,用户可能对$USER这个变量不太熟悉,需要解释清楚它的作用。同时,使用sudo和递归选项-R的风险也需要提醒,避免误操作其他系统文件。需要强调这个命令会修改整个目录结构的所有权,确认用户确实需要这样做,尤其是在生产环境中要谨慎。 可能还需要补充一些实际应用的例子,比如在安装软件时常见的问题,或者如何验证命令执行后的结果,比如用ls -l查看文件所有者是否变更。此外,可以提到如果用户属于某个特定的组,是否需要调整组部分,比如改成$USER:zookeeper之类的,但具体情况取决于实际需求。 总结来说,用户需要了解命令的每个部分及其作用,以及使用时的注意事项,确保他们正确安全地应用这个命令来解决权限问题。</think>--- ### 命令解读:`sudo chown -R $USER:$USER /opt/zookeeper` #### **1. 命令分解** ```bash sudo # 以管理员权限执行命令(需输入当前用户密码) chown # 修改文件/目录的所有者和所属组(Change Owner) -R # 递归操作(Recursive),包括目录下的所有子文件和子目录 $USER:$USER # 将所有者(Owner)和所属组(Group)均设置为当前登录用户 /opt/zookeeper # 目标路径(通常是ZooKeeper安装目录) ``` --- #### **2. 核心作用** - **权限修复**:将`/opt/zookeeper`目录及其所有内容的所有权**强制转移**给当前用户。 - **常见场景**: - 安装ZooKeeper后因权限不足导致无法读写配置文件(如`zoo.cfg`)。 - 使用`root`用户解压安装包后,普通用户无法操作该目录。 - 运行ZooKeeper服务时因权限问题报错(如`Permission denied`)。 --- #### **3. 参数详解** | 参数 | 说明 | |---------------|--------------------------------------------------------------------| | `$USER` | 环境变量,自动替换为当前用户名(例如用户名为`ubuntu`,则实际命令为`ubuntu:ubuntu`) | | `-R` | 递归修改目录内所有子项的所有权(否则仅修改目录本身) | | `/opt/zookeeper` | ZooKeeper默认安装路径,也可能是自定义路径(需根据实际情况替换) | --- #### **4. 风险与注意事项** - **慎用`-R`**:递归操作会修改目录下所有文件权限,若路径错误可能破坏系统文件。 - **生产环境谨慎使用**:若ZooKeeper由服务账户(如`zookeeper`用户)运行,需保持特定权限,直接赋权给`$USER`可能导致服务异常。 - **替代方案**:若仅需临时权限,可用`sudo chmod -R 755 /opt/zookeeper`开放读写权限,但不修改所有权。 --- #### **5. 验证命令效果** ```bash # 查看修改后的所有者和组 ls -ld /opt/zookeeper # 输出示例: # drwxr-xr-x 5 ubuntu ubuntu 4096 Jun 1 10:00 /opt/zookeeper ``` --- #### **6. 典型问题解决示例** **问题**:运行`zkServer.sh start`时报错 ```bash Error: Could not create the Java Virtual Machine. Error: A fatal exception has occurred. Program will exit. ``` **原因**:`/opt/zookeeper`目录权限归属`root`,普通用户无权执行Java进程。 **解决**:执行`sudo chown -R $USER:$USER /opt/zookeeper`后重试。 --- ### 总结 此命令通过递归修改所有权,**确保当前用户对ZooKeeper目录的完全控制权**,适用于开发调试环境。在生产环境中,建议通过用户组权限管理(如`chown -R zookeeper:zookeeper /opt/zookeeper`)实现更安全的权限隔离。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值