本文视频教程
https://www.bilibili.com/vide...
关注公众号 学习更多精彩课程
文章图片
使用三大核心语言Java、Python、Golang玩转zookeeper
使用Java原生api操作zookeeper
创建一个maven项目
创建一个maven项目
添加项目依赖
org.apache.zookeeper
zookeeper
3.4.8
https://mvnrepository.com/实现代码
package com.duoke360;
import org.apache.zookeeper.*;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String[] args) throws IOException, InterruptedException, KeeperException {
String connStr = "192.168.18.128:2181";
CountDownLatch countDown = new CountDownLatch(1);
Watcher watcher= event -> {
if (event.getState() == Watcher.Event.KeeperState.SyncConnected) {
System.err.println("eventType:"+event.getType());
if(event.getType()== Watcher.Event.EventType.None){
countDown.countDown();
}else if(event.getType()== Watcher.Event.EventType.NodeCreated){
System.out.println("listen:节点创建");
}else if(event.getType()== Watcher.Event.EventType.NodeChildrenChanged){
System.out.println("listen:子节点修改");
}
}
};
ZooKeeper zookeeper = new ZooKeeper(connStr, 5000,watcher);
countDown.await();
//注册监听,每次都要重新注册,否则监听不到
// 先创建一个根节点root
zookeeper.exists("/root/ghz", watcher);
// 创建节点
String result = zookeeper.create("/root/ghz", "老郭".getBytes(),
ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
System.out.println(result);
Thread.sleep(10);
// 获取节点
byte[] bs = zookeeper.getData("/root/ghz", true, null);
result = new String(bs);
System.out.println("创建节点后的数据是:" + result);
// 修改节点
zookeeper.setData("/root/ghz", "多课网-老郭".getBytes(), -1);
Thread.sleep(10);
bs = zookeeper.getData("/root/ghz", true, null);
result = new String(bs);
System.out.println("修改节点后的数据是:" + result);
// 删除节点
zookeeper.delete("/root/ghz", -1);
System.out.println("节点删除成功");
}
}
运行结果
eventType:None
eventType:NodeCreated
listen:节点创建
/root/ghz
创建节点后的数据是:老郭
eventType:NodeDataChanged
修改节点后的数据是:多课网-老郭
节点删除成功
eventType:NodeDeleted
使用java zkclient库操作zookeeper.md 创建一个maven项目 创建一个maven项目
添加依赖
com.101tec
zkclient
0.10
实现代码
package com.duoke360;
import org.I0Itec.zkclient.IZkDataListener;
import org.I0Itec.zkclient.ZkClient;
import org.apache.zookeeper.*;
import java.util.List;
public class Test {
public static void main(String[] args) throws InterruptedException {
String connStr = "192.168.18.128:2181";
ZkClient zk = new ZkClient(connStr);
// 注册【数据】事件
zk.subscribeDataChanges("/root/ghz", new IZkDataListener() {@Override
public void handleDataDeleted(String arg0) throws Exception {
System.err.println("数据删除:" + arg0);
}@Override
public void handleDataChange(String arg0, Object arg1) throws Exception {
System.err.println("数据修改:" + arg0 + "------" + arg1);
}
});
zk.subscribeChildChanges("/root", (arg0, arg1) -> {
System.err.println("子节点发生变化:" + arg0);
arg1.forEach(f -> {
System.out.println("content:" + f);
});
});
List list = zk.getChildren("/");
list.forEach(e -> {
System.out.println(e);
});
String res = zk.create("/root/ghz", "多课网-老郭", CreateMode.PERSISTENT);
System.out.println("创建节点/root/ghz成功:" + res);
zk.writeData("/root/ghz", "多课网-zookeeper");
System.out.println("修改节点/root/ghz数据成功");
res = zk.readData("/root/ghz");
System.out.println("节点数据:" + res);
Thread.sleep(1000);
zk.delete("/root/ghz");
System.out.println("删除节点/root/ghz成功");
Thread.sleep(1000);
System.out.println("------------------------------------------------");
for (int i = 0;
i < 10;
i++) {
zk.create("/root/ghz", "多课网-老郭", CreateMode.PERSISTENT);
Thread.sleep(1000);
zk.delete("/root/ghz");
Thread.sleep(1000);
}
}
}
运行结果
node20000000002
zookeeper
node10000000001
root
创建节点/root/ghz成功:/root/ghz
修改节点/root/ghz数据成功
节点数据:多课网-zookeeper
content:ghz
数据修改:/root/ghz------多课网-zookeeper
子节点发生变化:/root
数据修改:/root/ghz------多课网-zookeeper
删除节点/root/ghz成功
数据删除:/root/ghz
子节点发生变化:/root
------------------------------------------------
数据修改:/root/ghz------多课网-老郭
子节点发生变化:/root
content:ghz
数据删除:/root/ghz
子节点发生变化:/root
数据修改:/root/ghz------多课网-老郭
子节点发生变化:/root
content:ghz
数据删除:/root/ghz
子节点发生变化:/root
数据修改:/root/ghz------多课网-老郭
子节点发生变化:/root
使用Java curator库操作zookeeper 创建一个maven项目 创建一个maven项目
添加依赖
org.apache.curator
curator-recipes
4.2.0
实现代码
package com.duoke360;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
public class Test {
public static void main(String[] args) throws Exception {
String connStr = "192.168.18.128:2181";
CuratorFramework cur= CuratorFrameworkFactory.builder()
.connectString(connStr)
.connectionTimeoutMs(5000)
.retryPolicy(new ExponentialBackoffRetry(1000,3))
.build();
cur.start();
//连接//创建监听
PathChildrenCache cache=new PathChildrenCache(cur,"/root",true);
cache.start();
cache.rebuild();
cache.getListenable().addListener(new PathChildrenCacheListener() {
@Override
public void childEvent(CuratorFramework framwork, PathChildrenCacheEvent event) throws Exception {
System.err.println("节点发生变化:"+event.getType());
}
});
Stat stat=cur.checkExists().forPath("/root/ghz");
if(stat!=null){
System.out.println("/root/ghz 节点存在,直接删除");
cur.delete().forPath("/root/ghz");
}System.in.read();
System.out.println("准备创建 /root/ghz");
cur.create().withMode(CreateMode.PERSISTENT)
.forPath("/root/ghz", "多课网-老郭".getBytes());
System.out.println("节点 /root/ghz 创建成功");
Thread.sleep(1000);
byte[] bs=cur.getData().forPath("/root/ghz");
System.out.println("数据:"+new String(bs));
Thread.sleep(1000);
cur.delete().forPath("/root/ghz");
Thread.sleep(1000);
}
}
运行结果
test
准备创建 /root/ghz
节点 /root/ghz 创建成功
节点发生变化:CHILD_ADDED
数据:多课网-老郭
节点发生变化:CHILD_REMOVED
使用Python操作zookeeper 安装
pip install kazoo
连接 ZooKeeper
可通过 KazooClient 类直接连接 ZooKeeper ,支持多个 host ,端口默认 2181。
import json
from kazoo.client import KazooClientzk = KazooClient(hosts='192.168.18.128:2181')
zk.start()
创建节点
先看下 create() 方法定义
def create(self, path, value=https://www.it610.com/article/b"", acl=None, ephemeral=False,
sequence=False, makepath=False):
:param path: Path of node.
:param value: Initial bytes value of node.
:param acl: :class:`~kazoo.security.ACL` list.
:param ephemeral: Boolean indicating whether node is ephemeral
(tied to this session).
:param sequence: Boolean indicating whether path is suffixed
with a unique index.
:param makepath: Whether the path should be created if it
doesn't exist.
我们来解释下这些参数:
- path: 节点路径
- value: 节点对应的值,注意值的类型是 bytes
- ephemeral: 若为 True 则创建一个临时节点,session 中断后自动删除该节点。默认 False
- sequence: 若为 True 则在你创建节点名后面增加10位数字(例如:你创建一个 testplatform/test 节点,实际创建的是 testplatform/test0000000003,这串数字是顺序递增的)。默认 False
- makepath: 若为 False 父节点不存在时抛 NoNodeError。若为 True 父节点不存在则创建父节点。默认 False
from kazoo.client import KazooClientzk = KazooClient(hosts='192.168.18.128:2181')
zk.start()
# 创建节点:makepath 设置为 True ,父节点不存在则创建,其他参数不填均为默认
zk.create('/root/ghz',b'',makepath=True)
# 操作完后,别忘了关闭zk连接
zk.stop()
查看节点
KazooClient 类用提供
get_children()
和 get()
方法获取 子节点 和 节点对应的值from kazoo.client import KazooClientzk = KazooClient(hosts='192.168.18.128:2181')
zk.start()
# 获取某个节点下所有子节点
node = zk.get_children('/root')
# 获取某个节点对应的值
value = https://www.it610.com/article/zk.get('/root/ghz')
# 操作完后,别忘了关闭zk连接
zk.stop()
print(node,value)
更改节点
更改上文创建的 node 值,使用
set()
方法from kazoo.client import KazooClientzk = KazooClient(hosts='192.168.18.128:2181')
zk.start()
# 更改节点对应的value
zk.set('/root/ghz', b'duoke-ghz')
# 获取某个节点对应的值
value = https://www.it610.com/article/zk.get('/root/ghz')
zk.stop()
print(value)
删除节点
删除上文创建的节点,使用 delete() 方法
from kazoo.client import KazooClientzk = KazooClient(hosts='192.168.18.128:2181')
zk.start()
# 删除节点对应的value
zk.delete('/root/ghz',recursive=False)
zk.stop()
参数 recursive:若为 False,当需要删除的节点存在子节点,会抛异常 NotEmptyError 。若为True,则删除 此节点 以及 删除该节点的所有子节点watches 事件
zookeeper 所有读操作都有设置 watch 选项(get_children() 、get() 和 exists())。watch 是一个触发器,当检测到 zookeeper 有子节点变动 或者 节点value发生变动时触发。下面以 get() 方法为例。
from kazoo.client import KazooClientzk = KazooClient(hosts='192.168.18.128:2181')
zk.start()def test(event):
print('触发事件')if __name__ == "__main__":
# 节点必须存在,否则保存
zk.get('/root/ghz', watch=test)
print("第一次获取value")
zk.set('/root/ghz', b'duoke-ghz')
zk.get('/root/ghz', watch=test)
zk.set('/root/ghz', b'duoke-ghz2')
print("第二次获取value")zk.stop()
运行结果
第一次获取value
触发事件
第二次获取value
使用golang操作zookeeper 下载包
go get github.com/samuel/go-zookeeper
连接到Server
package mainimport (
"fmt"
"time""github.com/samuel/go-zookeeper/zk"
)func conn() *zk.Conn {
var hosts = []string{"192.168.18.128:2181"}
conn, _, err := zk.Connect(hosts, time.Second*5)
defer conn.Close()
if err != nil {
fmt.Println(err)
return nil
} else {
fmt.Println("连接成功!")
return conn
}
}func main() {
conn()
}
创建节点
func create() {
var conn *zk.Conn = conn()
defer conn.Close()
var path = "/home"
var data = https://www.it610.com/article/[]byte("多课网")
var flags int32 = 0
//flags有4种取值:
//0:永久,除非手动删除
//zk.FlagEphemeral = 1:短暂,session断开则改节点也被删除
//zk.FlagSequence= 2:会自动在节点后面添加序号
//3:Ephemeral和Sequence,即,短暂且自动添加序号
var acls = zk.WorldACL(zk.PermAll) //控制访问权限模式p, err_create := conn.Create(path, data, flags, acls)
if err_create != nil {
fmt.Println(err_create)
return
}
fmt.Println("create:", p)
}
修改节点
func set() {
var conn *zk.Conn = conn()
defer conn.Close()
var path = "/home"
var data = https://www.it610.com/article/[]byte("多课网-老郭")
conn.Set(path, data, -1)
b, _, _ := conn.Get(path)
fmt.Println("数据:" + string(b))
}
删除节点
func del() {
var conn *zk.Conn = conn()
defer conn.Close()
var path = "/home"
err := conn.Delete(path, -1)
if err != nil {
fmt.Println("删除失败!")
} else {
fmt.Println("删除成功!")
}
}
watch
func callback(event zk.Event) {
fmt.Println("*******************")
fmt.Println("path:", event.Path)
fmt.Println("type:", event.Type.String())
fmt.Println("state:", event.State.String())
fmt.Println("*******************")
}func watch() {var hosts = []string{"192.168.18.128:2181"}
option := zk.WithEventCallback(callback)conn, _, err := zk.Connect(hosts, time.Second*5, option)
defer conn.Close()
if err != nil {
fmt.Println(err)
return
}
var path = "/home"
_, _, _, err = conn.ExistsW(path)
if err != nil {
fmt.Println(err)
return
}// 创建
create(conn)time.Sleep(time.Second * 2)_, _, _, err = conn.ExistsW(path)
if err != nil {
fmt.Println(err)
return
}
// 删除
del(conn)}
关注公众号 学习更多精彩课程 【使用三大核心语言Java、Python、Golang玩转zookeeper】
文章图片
推荐阅读
- 【golang】leetcode中级-字母异位词分组&无重复字符的最长子串
- 彻底理解Golang Map
- kratos线上开源年会它来啦~
- 深入浅出 Golang 资源嵌入方案(go-bindata篇)
- 深入浅出 Golang 资源嵌入方案(前篇)
- golang 经典案例总结
- Go实战 | 基于有向无环图的并发执行流的实现
- Golang 数组和切片
- Go JSON编码与解码()
- golang map基础知识