【收藏篇】Zookeeper单机部署、必备命令、场景实战

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

前言

昨天花哥在第一篇文章中介绍了Zookeeper是什么,大家对它应该也有了一个初步的概念,今天呢,我们就实际操作一波,看它是如何部署到我们的机器上,在代码中又是如何应用的。

单机版安装(windows)

  1. 打开Zookeeper官网 首页,点击Download,就可以跳转到下载页,根据需要选择对应的版本。

image-20211102094012711.png

  1. 如果官网访问失败,花哥也将【3.6.3】、【3.7.0】两个版本上传到百度网盘,有需要的小伙伴可以直接下载

链接:pan.baidu.com/s/19wHXUKTf… 提取码:chwm

  1. 将压缩包解压,打开conf目录,将zoo_sample.cfg拷贝一份并命名为zoo.cfg

image.png

  1. 上述配置完毕后,打开bin目录,双击zkServer.cmd启动服务端
  2. 服务启动完成,双击zkCli.cmd即可以进行测试

注意:zookeeper依赖java环境,因此在安装前,保证操作系统中java环境正常。

单机版安装(linux)

  1. 下载解压
1
2
3
4
shell复制代码# cd /usr/local
# wget https://dlcdn.apache.org/zookeeper/zookeeper-3.7.0/apache-zookeeper-3.7.0-bin.tar.gz
# tar -zxvf apache-zookeeper-3.7.0-bin.tar.gz
# cd apache-zookeeper-3.7.0-bin
  1. 修改配置
1
shell复制代码# cp conf/zoo_sample.cfg conf/zoo.cfg
  1. 启动服务
1
shell复制代码# bin/zkServer.sh start
  1. 启动客户端
1
shell复制代码# bin/zkCli.sh

注意:如果wget无法使用,可以使用yum -y install wget先将其安装,或者直接将zookeeper包下载到本地,然后上传至服务器。

配置文件说明

在单机版中,我们只需要配置以下三个参数就可以正常启动

1
2
3
4
5
6
ini复制代码#心跳时间,单位毫秒
tickTime = 2000
#数据存放目录
dataDir = /usr/local/zookeeper
#客户端连接端口
clientPort = 2181

当然,在实际应用中,上面三个参数可能是不够的,这时我们可以在官网指南中查看每一个配置项的作用,根据实际需求选择。
\

image.png

命令使用说明

  • 使用ls可以查看zookeeper当前包含的节点

image.png

  • 使用create创建一个新的子节点

image.png

  • 使用ls再来看下根目录下包含的子节点,testData已经被创建

image.png

  • 使用get查看节点内容

image.png

  • 使用set设置节点内容

image.png

  • 使用delete删除节点

image.png

常用命令介绍

  • 客户端命令

命令 说明 示例
ls 获取节点 ls /
create 创建子节点 create /testData 100
delete 删除节点 delete /testData
get 从指定节点读取数据 get -s /testData
set 设置数据到指定节点 set /testData 200help
help 查看帮助
quit 退出客户端
  • 服务命令

命令 说明
sh bin/zkServer.sh start 启动zk服务
sh bin/zkServer.sh stop 停止zk服务
sh bin/zkServer.sh restart 重启zk服务
sh bin/zkServer.sh status 查看服务状态

代码测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
java复制代码package com.basic.business.demo;

import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.WatchedEvent;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.Watcher.Event.EventType;
import org.apache.zookeeper.Watcher.Event.KeeperState;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

/**
* zk测试demo
*
*/
public class ZookeeperDemo implements Watcher {

   private static ZooKeeper zk = null;
   private static Stat stat = new Stat();

   public static void main(String[] args) throws Exception {
       //被监听的节点
       String path = "/testData";
       //连接zookeeper并注册监听器
       zk = new ZooKeeper("127.0.0.1:2181", 5000, new ZookeeperDemo());
       //注册监听器,监听节点/testData值的变化
       zk.getData(path,true,stat);
       Thread.sleep(Integer.MAX_VALUE);
  }

   public void process(WatchedEvent event) {
       //zk连接成功事件
       if (KeeperState.SyncConnected == event.getState()) {
           //zk节点数据变化时通知事件
           if (event.getType() == EventType.NodeDataChanged) {
               try {
                   System.out.println("修改后的值:" + new String(zk.getData(event.getPath(), true, stat)));
              } catch (Exception e) {
              }
          }
      }
  }
}

然后连接zk客户端,修改子节点/testData的内容,就能观察到idea控制台能够打印出修改后的内容。

执行结果8.gif

官网实例

有兴趣的小伙伴,可以跟着官网的示例走一下,共计有两个类,代码贴出来,花哥就不再演示了。地址:zookeeper.apache.org/doc/current…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
java复制代码//Executor.java

/**
* 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;

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) {
}

}
}

public void exists(byte[] data) {
if (data == null) {
if (child != null) {
System.out.println("Killing process");
child.destroy();
try {
child.waitFor();
} catch (InterruptedException e) {
}
}
child = null;
} else {
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();
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
java复制代码//DataMonitor.java

/**
* 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;
}
}
}

写在最后

今天介绍了zookeeper的单机部署和一些常用命令,已经在java中如何使用,下一章花哥对Zookeeper的核心内容进行讲解,如果觉得文章有一些不妥,小伙伴们可以大胆提出来,一起进步,共同学习。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%