JavaRush /Java 博客 /Random-ZH /动物园管理员或动物园管理员的生活是什么样的
Viacheslav
第 3 级

动物园管理员或动物园管理员的生活是什么样的

已在 Random-ZH 群组中发布
动物园管理员或动物园工作人员的生活方式 - 1

介绍

Java 应用程序通常有不同的配置。例如,地址和连接端口。例如,如果我们使用Properties类,它可能看起来像这样:
public static void main(String []args) {
	Properties props = new Properties();
	props.setProperty("host", "www.tutorialspoint.com");
	System.out.println("Hello, " + props.getProperty("host"));
}
这似乎就足够了,因为…… 我们可以从文件中获取属性。一切似乎都在一台机器上与我们相处得很好。但是想象一下,我们的系统开始由彼此分离的不同系统组成?这样的系统也称为分布式系统。在维基百科上,您可以找到以下定义:分布式系统是其组件位于不同网络计算机上的系统,这些计算机相互通信并通过相互交换消息来协调其操作。你可以看下图:
动物园管理员或动物园工作人员的生活方式 - 2
通过这种方法,单个系统被分为多个组件。配置是一个单独的公共组件。其他每个组件都充当配置组件的客户端。这种情况称为“分布式配置”。分布式配置有许多不同的实现。在今天的评论中,我建议熟悉其中之一,称为 Zookeeper。
动物园管理员或动物园工作人员的生活方式 - 3

动物园管理员

了解 Zookeeper 的路径始于其官方网站:zookeeper.apache.org在官方网站上,您需要转到“下载” 部分。在本部分中,下载 .tar.gz 格式的存档,例如“zookeeper-3.4.13.tar.gz”。tar 是 Unit 系统的传统存档格式。gz - 表示使用 gzip 来压缩存档。如果我们在 Windows 机器上工作,那么这不应该困扰我们。大多数现代归档程序(例如7-zip)可以在 Windows 上与它们完美配合。让我们将内容提取到某个目录中。同时,我们将看到差异 - 在解压状态下的磁盘上,它将占用大约 60 兆字节,而我们下载的存档大小约为 35 兆字节。正如您所看到的,压缩确实有效。现在您需要启动 Zookeeper。总的来说,Zookeeper是一种服务器。Zookeeper 可以以两种模式之一运行:StandaloneReplicated。让我们考虑最简单的选项,也称为第一个选项 - 独立模式。为了运行 Zookeper,它需要一个配置文件。因此,让我们在这里创建它:[КаталогРаспаковкиZookeeper]/conf/zoo.cfg。对于 Windows,我们将使用 Medium 的建议:“在 Windows 上安装 Apache ZooKeeper ”。配置文件的内容将是这样的:
tickTime=2000
dataDir=C:/zookeeper-3.4.13/data
clientPort=2181
让我们添加包含zookeper根目录路径的ZOOKEEPER_HOME环境变量(如medium上的说明),同时将以下片段添加到PATH环境变量中:另外;%ZOOKEEPER_HOME%\bin; ,dataDir中指定的目录必须存在,否则Zookeeper将不会能够启动服务器。现在我们可以使用命令:zkServer 安全地启动服务器。由于Zookeeper目录已添加到path环境变量中,我们可以从任何地方调用Zookeeper命令,而不仅仅是从bin目录。
动物园管理员或动物园工作人员的生活方式 - 4

Z节点

正如《 Zookeeper 概述》中所述,Zookeeper 中的数据以ZNode (节点)的形式表示,这些 ZNode 被组织成树形结构。也就是说,每个 ZNode 都可以包含数据并具有子 ZNode。关于ZNode组织的更多信息可以在Zookeeper文档中找到:“数据模型和分层命名空间”。为了与 Zookeeper 和 ZNode 配合使用,我们将使用Zookeeper CLI(命令行界面)。之前,我们使用 zkServer 命令启动服务器。现在,要连接,让我们执行。zkCli.cmd -server 127.0.0.1:2181 如果成功,将创建与 Zookeeper 的连接会话,我们将看到大约以下输出:
动物园管理员或动物园工作人员的生活方式 - 5
有趣的是,即使在安装之后,Zookeeper 就已经拥有了 ZNode。它有以下路径:/zookeeper/quota
动物园管理员或动物园工作人员的生活方式 - 6
这些就是所谓的“配额”。正如“ Apache ZooKeeper Essentials ”中所述,每个 ZNode 都可以有一个与之关联的配额,限制它可以存储的数据。可以指定 znode 数量和存储数据量的限制。而且,如果超过这个限制,那么对ZNode的操作不会被取消,但会收到有关超过限制的警告。建议阅读《ZooKeeper 程序员指南:ZNodes》中有关 ZNode 的内容。其中的一些示例说明了如何使用 ZNode:
动物园管理员或动物园工作人员的生活方式 - 7
我还想指出 ZNode 是不同的。常规 ZNode(除非您指定其他标志)的类型为“ permanent ”。有一个“临时节点”类型的 ZNode。此类 ZNode 仅在创建它们的 Zookeeper 连接会话期间存在。有一个“序列节点”类型的 ZNode。这些 ZNode 附加有序列中的编号以确保唯一性。序列节点可以是持久的或短暂的。这里还推荐一些有关 ZNode 的背景信息:“ Zookeeper ZNodes – 特征和示例”。
动物园管理员或动物园工作人员的生活方式 - 8

Z节点观察者

我还想谈谈观察者。关于它们的详细信息写在 Zookeeper 的文档中:“ ZooKeeper Watches ”。简而言之,观察者是由某个事件触发的一次性触发器。通过执行 getData()、getChildren() 或 Exists() 操作检索数据,我们可以创建触发器作为附加操作。Zookeeper 确保事件的处理顺序。此外,文档指出,在我们看到新的 ZNode 值之前,我们将看到一个有关将旧值更改为新值的事件。您可以在此处阅读有关观察者的更多信息:“ ZooKeeper 观察 – 功能和保证”。为了尝试这个,让我们再次使用CLI:假设我们有一些 ZNode,其值用于存储某些服务的状态:
[zk: 127.0.0.1:2181(CONNECTED) 0] create /services/service1/status stopped
Created /services/service1/status
[zk: 127.0.0.1:2181(CONNECTED) 1] get /services/service1/status [watch]
stopped
现在,如果数据/services/service1/status发生变化,我们的一次性触发器将触发:
动物园管理员或动物园工作人员的生活方式 - 9
有趣的是,当连接到 Zookeeper 时,我们还可以看到观察者是如何工作的:
WATCHER::
WatchedEvent state:SyncConnected type:None path:null
SyncConnected是可能的 Zookeper 事件之一。有关它的更多详细信息可以在 API 描述中找到。
动物园管理员或动物园工作人员的生活方式 - 10

动物园管理员和Java

现在我们对 Zookeeper 的功能有了一些基本的了解。现在让我们通过 Java 而不是通过 CLI 来使用它。为此,我们需要一个 Java 应用程序,在其中我们将了解如何与 Zookeeper 一起工作。为了创建应用程序,我们将使用Gradle项目构建系统。我们将使用“ Gradle Build Init 插件”创建项目。为此,我们运行命令:gradle init --type java-application 如果 Gradle 要求我们澄清问题,那么我们将保留默认值(只需按 Enter)。现在让我们打开构建脚本,即 构建.gradle 文件。它包含对我们的项目的组成以及它所依赖的工件(库、框架)的描述。因为 我们想要使用Zookeeper,那么我们需要添加它。因此,我们将 Zookeeper 的依赖项添加到依赖项块中:
dependencies {
    implementation 'org.apache.zookeeper:zookeeper:3.4.13'
您可以在评论中阅读有关 Gradle 的更多信息:“ Gradle 简介”。因此,我们有一个 Java 项目,我们将 Zookeeper 库连接到它。现在让我们写点东西吧。我们记得,使用 CLI 我们连接了这样的东西:zkCli.cmd -server 127.0.0.1:2181 让我们在 App 类的 main 方法中声明“server”属性:
String server = "127.0.0.1:2181";
连接不是一个即时动作。我们必须以某种方式在程序执行的主线程中等待连接的发生。因此,我们需要一把锁。下面我们来声明一下:
Object lock = new Object();
现在我们需要有人告诉我们连接已经建立。我们记得,当我们通过 CLI 执行此操作时,观察者为我们工作。所以在 Java 代码中一切都是完全相同的。我们的观察者将显示一条有关成功完成的消息,并通过锁通知等待的每个人。我们来写一个观察者:
Watcher connectionWatcher = new Watcher() {
	public void process(WatchedEvent we) {
		if (we.getState() == Event.KeeperState.SyncConnected) {
			System.out.println("Connected to Zookeeper in " + Thread.currentThread().getName());
			synchronized (lock) {
            	lock.notifyAll();
            }
		}
	}
};
现在让我们添加到zooKeeper服务器的连接:
int sessionTimeout = 2000;
ZooKeeper zooKeeper = null;
synchronized (lock) {
	zooKeeper = new ZooKeeper(server, sessionTimeout, connectionWatcher);
	lock.wait();
}
这里一切都很简单。当在程序主线程中执行main方法时,我们获取锁并向zookeeper请求连接。同时,我们释放锁并等待,直到其他人抢到锁并通知我们可以继续。当连接建立后,观察者就会开始工作。他将检查 SyncConnected 事件是否已到达(我们记得,这是观察者通过 CLI 捕获的事件),然后写入一条消息。接下来,我们获取锁(因为主线程之前释放了它)并通知所有等待锁的线程我们可以继续。事件处理线程退出同步块,从而释放锁。主线程收到通知,等待锁释放后,继续执行,因为 在收到锁之前,它将无法退出同步块并继续工作。因此,使用多线程和 Zookeeper API,我们可以执行各种操作。Zookeeper API 比 CLI 允许的范围要广泛得多。例如:
// Creation нового узла
String znodePath = "/zookeepernode2";
List<ACL> acls = ZooDefs.Ids.OPEN_ACL_UNSAFE;
if (zooKeeper.exists(znodePath, false) == null) {
	zooKeeper.create(znodePath, "data".getBytes(), acls, CreateMode.PERSISTENT);
}

// Получение данных из узла
byte[] data = zooKeeper.getData(znodePath, null, null);
System.out.println("Result: " + new String(data, "UTF-8"));
正如你所看到的,在创建节点时我们可以配置ACL。这是另一个重要特征。ACL 是适用于 ZNode 操作的权限。设置比较多,建议大家详细参考官方文档:《Zookeeper ACL权限》。
动物园管理员或动物园工作人员的生活方式 - 11

结论

我们为什么读这个?因为Zookeeper被用于其他流行的技术中。例如,Apache Kafka需要Zookeeper,您可以在“ Kafka快速入门指南”中阅读有关Zookeeper的信息。它也用于 NOSQL 数据库 HBase,您可以在他们的“ HBase 快速入门指南”中阅读更多信息。事实上,许多其他项目都使用 Zookeeper。其中一些列在“在现实世界中使用 Zookeeper ”。我希望我回答了“为什么”这个问题。现在最重要的问题是:“下一步是什么?” 首先,您可以阅读以下有关 Apache Zookeeper 主题的书籍: 其次,有关于Zookeeper的精彩视频报道。推荐观看: 第三,有几篇有用的文章可以补充世界的图景: 这是一篇非常简短的评论,但作为介绍性的文字,我希望它会有用。#维亚切斯拉夫
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION