1. 程式人生 > 其它 >zookeeper 客戶端_【go語言】一文輕鬆實現ZooKeeper的客戶端操作

zookeeper 客戶端_【go語言】一文輕鬆實現ZooKeeper的客戶端操作

技術標籤:zookeeper 客戶端zookeeper 認證zookeeper客戶端

ZooKeeper是分散式協調服務,用處非常廣,例如訊息系統kafka、大資料hadoop、分散式資料庫hbase、搜尋引擎solr、分散式資源管理框架mesos等。同類產品有etcd、consul、eureka,大體功能是服務註冊和發現,比如用在微服務框架中。ZooKeeper原始碼是用java來實現的,第三方比較好用的客戶端也是java實現的,比如curator和zkclient。

在編寫go示例程式碼前,先安裝zookeeper包:

# go get github.com/samuel/go-zookeeper/zk

請看示例程式碼:

package main
​
import (
  "fmt"
  "github.com/samuel/go-zookeeper/zk"
  "log"
  "os"
  "time"
)
​
// 定義常量
const (
  AUTH_USER = "fullstackcareer"
  AUTH_PWD = "FullStackCareer"
  PATH = "/fullstackcareer"
  DATA1 = "data1"
  DATA2 = "data2"
)
​
// 定義客戶端結構體
type ZkClient struct {
  ConnectString []string
  ZkConn *zk.Conn
  zkAcl []zk.ACL
}
​
// 新建客戶端
func NewZkClient(connectString []string) *ZkClient {
  client :=ZkClient{
    ConnectString: connectString[:],
    ZkConn:        nil,
    zkAcl:         zk.DigestACL(zk.PermAll, AUTH_USER, AUTH_PWD),
  }
  return &client
}
​
// 關閉客戶端
func (client *ZkClient) Close() error {
  if client.ZkConn != nil {
    client.ZkConn.Close()
  }
  return nil
}
​
// 建立連線
func(client *ZkClient) Connect(sessionTimeout time.Duration) error {
  // 判斷連線是否存在
  if client.ZkConn != nil {
    client.Close()
  }
​
  // 建立連線
  c, _, err :=zk.Connect(client.ConnectString, sessionTimeout)
  if err != nil {
    return err
  }
​
  // ACL 認證
  auth :=AUTH_USER + ":" + AUTH_PWD
  if err := c.AddAuth("digest", []byte(auth)); err != nil {
    client.Close()
    return err
  }
​
  // 賦值到結構體變數,複用該連線
  client.ZkConn = c
  return nil
}
​
// 建立 znode
func (client *ZkClient) Create(path string, data []byte) error {
  _, err := client.ZkConn.Create(path, data, 0, client.zkAcl)
  return err
}
​
// 判斷 znode 是否存在
func (client *ZkClient) Exist(path string) (bool, error) {
  isExist, _, err := client.ZkConn.Exists(path)
  return isExist, err
}
​
// 設定 znode 值
func (client *ZkClient) Set(path string, data []byte, version int32) error {
  _, err :=client.ZkConn.Set(path, data, version)
  return err
}
​
// 獲取 znode 的值
func (client *ZkClient) Get(path string) (string, error) {
  data, _, err := client.ZkConn.Get(path)
  return string(data), err
}
​
// 刪除 znode
func (client *ZkClient) delete(path string) error {
  err := client.ZkConn.Delete(path, -1)
  return err
}
​
func main() {
  // 傳參合法性判斷
  if len(os.Args) != 2 {
    fmt.Println("usage: ", os.Args[0], "connectString")
    os.Exit(-1)
  }
  connectString := []string{os.Args[1]}
​
  // 建立客戶端
  zkClient := NewZkClient(connectString)
  if zkClient != nil {
    log.Println("建立zookeeper客戶端成功")
  } else {
    log.Fatal("建立zookeeper客戶端失敗")
  }
​
  // 建立連線
  err := zkClient.Connect(60 * time.Second)
  if err != nil {
    log.Fatal("建立zookeeper連線失敗")
  } else {
    log.Println("建立zookeeper連線成功")
  }
​
  // 建立 znode
  err = zkClient.Create(PATH, []byte(DATA1))
  if err != nil {
    log.Fatal("建立 " + PATH + " 失敗")
  } else {
    log.Println("建立 " + PATH + " 成功")
  }
​
  // 判斷 znode 是否存在
  isExist, err := zkClient.Exist(PATH)
  if err == nil {
    if isExist == true {
      log.Println("znode " + PATH + " 存在")
    } else {
      log.Fatal("znode " + PATH + " 不存在")
    }
  }
​
  // 設定 znode 的值
  err = zkClient.Set(PATH, []byte(DATA2), -1)
  if err != nil {
    log.Fatal("設定 znode " + PATH + " 值 " + DATA2 + " 失敗")
  } else {
    log.Println("設定 znode " + PATH + " 值 " + DATA2 + " 成功")
  }
​
  // 獲取 znode 的值
  data, err := zkClient.Get(PATH)
  if err != nil {
    log.Fatal("獲取 znode " + PATH + "值失敗")
  } else {
    log.Print("獲取 znode " + PATH + "值為 " + data)
  }
​
  // 刪除 znode
  err = zkClient.delete(PATH)
  if err != nil {
    log.Fatal("刪除 znode " + PATH + " 失敗")
  } else {
    log.Println("刪除 znode " + PATH + " 成功")
  }
​
  // 關閉客戶端
  err = zkClient.Close()
  if err == nil {
    log.Println("關閉客戶端成功")
  }
}

編譯程式碼,執行:

# go build zookeeper.go
# ./zookeeper localhost:2181
2020/02/16 17:44:13 建立zookeeper客戶端成功
2020/02/16 17:44:13 Connected to [::1]:2181
2020/02/16 17:44:13 authenticated: id=72057621439774727, timeout=40000
2020/02/16 17:44:13 re-submitting `0` credentials after reconnect
2020/02/16 17:44:13 建立zookeeper連線成功
2020/02/16 17:44:13 建立 /fullstackcareer 成功
2020/02/16 17:44:13 znode /fullstackcareer 存在
2020/02/16 17:44:13 設定 znode /fullstackcareer 值 data2 成功
2020/02/16 17:44:13 獲取 znode /fullstackcareer值為 data2
2020/02/16 17:44:13 刪除 znode /fullstackcareer 成功
2020/02/16 17:44:13 recv loop terminated: err=EOF
2020/02/16 17:44:13 send loop terminated: err=<nil>
2020/02/16 17:44:13 關閉客戶端成功

總結

本文的示例程式碼實現了對ZooKeeper常見的操作,包括建立客戶端、建立連線、建立znode、判斷znode是否存在、更新znode值、獲取znode值、關閉客戶端。需要注意的是,文中的程式碼是利用面向物件的思維設計的,在實際工作中也有參考意義。

1b0f19f93f53a53960c13cbaf5bbec7d.png