Zookeeper单机部署、必备命令、场景实战
前言
昨天花哥在第一篇文章中介绍了Zookeeper是什么,大家对它应该也有了一个初步的概念,今天呢,我们就实际操作一波,看它是如何部署到我们的机器上,在代码中又是如何应用的。
单机版安装(windows)
打开Zookeeper官网 首页,点击Download,就可以跳转到下载页,根据需要选择对应的版本。
如果官网访问失败,花哥也将【3.6.3】、【3.7.0】两个版本上传到百度网盘,有需要的小伙伴可以直接下载
链接:pan.baidu.com/s/19wHXUKTf… 提取码:chwm
将压缩包解压,打开conf目录,将zoo_sample.cfg拷贝一份并命名为zoo.cfg
上述配置完毕后,打开bin目录,双击zkServer.cmd启动服务端
服务启动完成,双击zkCli.cmd即可以进行测试
注意:zookeeper依赖java环境,因此在安装前,保证操作系统中java环境正常。
单机版安装(linux)
下载解压
# 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 复制代码
修改配置
# cp conf/zoo_sample.cfg conf/zoo.cfg 复制代码
启动服务
# bin/zkServer.sh start 复制代码
启动客户端
# bin/zkCli.sh 复制代码
注意:如果wget无法使用,可以使用yum -y install wget先将其安装,或者直接将zookeeper包下载到本地,然后上传至服务器。
配置文件说明
在单机版中,我们只需要配置以下三个参数就可以正常启动
#心跳时间,单位毫秒 tickTime = 2000 #数据存放目录 dataDir = /usr/local/zookeeper #客户端连接端口 clientPort = 2181 复制代码
当然,在实际应用中,上面三个参数可能是不够的,这时我们可以在官网指南中查看每一个配置项的作用,根据实际需求选择。 \
命令使用说明
使用ls可以查看zookeeper当前包含的节点
使用create创建一个新的子节点
使用ls再来看下根目录下包含的子节点,testData已经被创建
使用get查看节点内容
使用set设置节点内容
使用delete删除节点
常用命令介绍
客户端命令
命令 | 说明 | 示例 |
---|---|---|
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 | 查看服务状态 |
代码测试
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控制台能够打印出修改后的内容。
官网实例
有兴趣的小伙伴,可以跟着官网的示例走一下,共计有两个类,代码贴出来,花哥就不再演示了。地址:zookeeper.apache.org/doc/current…
//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(); } } } } 复制代码
//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的核心内容进行讲解,如果觉得文章有一些不妥,小伙伴们可以大胆提出来,一起进步,共同学习。
作者:JavaGieGie
链接:https://juejin.cn/post/7025887917243383844