golang使用较多的zookeeper client有gozk,go-zookeeper
本篇采用:go-zookeeper(文档比较全一点)
话不多说,直接撸代码:
package main
import (
"fmt"
"github.com/samuel/go-zookeeper/zk"
"time"
)
var (
path = "/test"
)
// 增 zk中有4中节点 永久节点 永久有序节点 临时节点 临时有序节点
func add(conn *zk.Conn) {
var data = []byte("test value")
// flags有4种取值:
// 0:永久,除非手动删除
// zk.FlagEphemeral = 1:临时,session断开则该节点也被删除
// zk.FlagSequence = 2:有序节点,会自动在节点后面添加序号
// 3:Ephemeral和Sequence,临时有序节点
var flags int32 = 0
// 获取访问控制权限
acls := zk.WorldACL(zk.PermAll)
s, err := conn.Create(path, data, flags, acls)
if err != nil {
fmt.Printf("创建失败: %v\n", err)
return
}
fmt.Printf("创建: %s 成功", s)
}
// 查
func get(conn *zk.Conn) {
data, _, err := conn.Get(path)
if err != nil {
fmt.Printf("查询%s失败, err: %v\n", path, err)
return
}
fmt.Printf("%s 的值为 %s\n", path, string(data))
}
func modify(conn *zk.Conn) {
newData := []byte("hello zookeeper")
_, sate, _ := conn.Get(path)
_, err := conn.Set(path, newData, sate.Version)
if err != nil {
fmt.Printf("数据修改失败: %v\n", err)
return
}
fmt.Println("数据修改成功")
}
// 删
func del(conn *zk.Conn) {
_, sate, _ := conn.Get(path)
err := conn.Delete(path, sate.Version)
if err != nil {
fmt.Printf("数据删除失败: %v\n", err)
return
}
fmt.Println("数据删除成功")
}
func main() {
// 创建zk连接地址
hosts := []string{"127.0.0.1:2181"}
// 连接zk
conn, _, err := zk.Connect(hosts, time.Second*5)
defer conn.Close()
if err != nil {
fmt.Println(err)
return
}
fmt.Println("添加节点:")
add(conn)
get(conn)
fmt.Println("修改节点:")
modify(conn)
get(conn)
fmt.Println("删除节点:")
del(conn)
get(conn)
}
结果如下:(节点删除后,查询返回了错误)
监听机制:
全局监听:
package main
import (
"fmt"
"github.com/samuel/go-zookeeper/zk"
"time"
)
var (
hosts = []string{"127.0.0.1:2181"}
path = "/test"
flags int32 = zk.FlagEphemeral
data = []byte("zk data 001")
acls = zk.WorldACL(zk.PermAll)
)
func main() {
// 创建监听的option,用于初始化zk
eventCallbackOption := zk.WithEventCallback(callback)
// 连接zk
conn, _, err := zk.Connect(hosts, time.Second*5, eventCallbackOption)
defer conn.Close()
if err != nil {
fmt.Println(err)
return
}
// 开始监听path
_, _, _, err = conn.ExistsW(path)
if err != nil {
fmt.Println(err)
return
}
// 触发创建数据操作
create(conn, path, data)
//再次监听path
_, _, _, err = conn.ExistsW(path)
if err != nil {
fmt.Println(err)
return
}
// 触发删除数据操作
del(conn, path)
}
// zk watch 回调函数
func callback(event zk.Event) {
// zk.EventNodeCreated
// zk.EventNodeDeleted
fmt.Println("###########################")
fmt.Println("path: ", event.Path)
fmt.Println("type: ", event.Type.String())
fmt.Println("state: ", event.State.String())
fmt.Println("###########################")
}
// 创建数据
func create(conn *zk.Conn, path string, data []byte) {
_, err := conn.Create(path, data, flags, acls)
if err != nil {
fmt.Printf("创建数据失败: %v\n", err)
return
}
fmt.Println("创建数据成功")
}
// 删除数据
func del(conn *zk.Conn, path string) {
_, stat, _ := conn.Get(path)
err := conn.Delete(path, stat.Version)
if err != nil {
fmt.Printf("删除数据失败: %v\n", err)
return
}
fmt.Println("删除数据成功")
}
输出中多了一些eventsession等信息,如下图所示:
局部监听:
package main
import (
"fmt"
"github.com/samuel/go-zookeeper/zk"
"time"
)
var (
hosts = []string{"127.0.0.1:2181"}
path = "/test"
flags int32 = zk.FlagEphemeral
data = []byte("zk data 001")
acls = zk.WorldACL(zk.PermAll)
)
func main() {
// 连接zk
conn, _, err := zk.Connect(hosts, time.Second*5)
defer conn.Close()
if err != nil {
fmt.Println(err)
return
}
// 开始监听path
_, _, event, err := conn.ExistsW(path)
if err != nil {
fmt.Println(err)
return
}
// 协程调用监听事件
go watchZkEvent(event)
// 触发创建数据操作
create(conn, path, data)
// 开始监听path
_, _, event, err = conn.ExistsW(path)
if err != nil {
fmt.Println(err)
return
}
go watchZkEvent(event)
del(conn,path)
time.Sleep(time.Second*1)
}
// zk 回调函数
func watchZkEvent(e <-chan zk.Event) {
event := <-e
fmt.Println("###########################")
fmt.Println("path: ", event.Path)
fmt.Println("type: ", event.Type.String())
fmt.Println("state: ", event.State.String())
fmt.Println("###########################")
}
// 创建数据
func create(conn *zk.Conn, path string, data []byte) {
_, err := conn.Create(path, data, flags, acls)
if err != nil {
fmt.Printf("创建数据失败: %v\n", err)
return
}
fmt.Println("创建数据成功")
}
// 删除数据
func del(conn *zk.Conn, path string) {
_, stat, _ := conn.Get(path)
err := conn.Delete(path, stat.Version)
if err != nil {
fmt.Printf("删除数据失败: %v\n", err)
return
}
fmt.Println("删除数据成功")
}
代码在最后稍微延时,否则可能来不及输出程序就结束了。