package main
import (
"encoding/json"
"fmt"
"github.com/samuel/go-zookeeper/zk"
"strconv"
"strings"
"time"
"net"
)
var zkservers string
var conn *zk.Conn
type zklistener func()
func testlisten() {
fmt.Println("listen test")
}
//獲取本機的ip地址
func localIP() string {
addrs, err := net.InterfaceAddrs()
if err != nil {
return ""
}
for _, address := range addrs {
// 檢查ip地址判斷是否迴環地址
if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
if ipnet.IP.To4() != nil {
return ipnet.IP.String()
}
}
}
return ""
}
// 首先調用此方法設置zk地址
// 初始化zk server
func SetZkServers(servers string, listeners ...zklistener) {
if zkservers != servers {
zkservers = servers
initConn()
for _, listener := range listeners {
listener()//定義當設置zk server時候需要通知的回調函數,做一些操作
}
}
}
func Register(path, port string) {
ip := localIP()
if ip == "" {
panic("get local ip error")
}
zkKey := ip + ":" + port
value := make(map[string]interface{})
value["host"] = ip
p, _ := strconv.Atoi(port)
value["port"] = p
zkVal, _ := json.Marshal(value)
go func() {
for {
var exist bool
var err error
registerPath := path + "/" + zkKey
exist, _, err = conn.Exists(registerPath)
if err != nil {
fmt.Println("Exist Err:", err)
time.Sleep(time.Second)
continue
}
if !exist {
//flag = zk.FlagEphemeral
//flags有4種取值:
//0:永久,除非手動刪除
//zk.FlagEphemeral = 1:短暫,session斷開則改節點也被刪除,session維持時間爲zk.Connect的第二個參數
//zk.FlagSequence = 2:會自動在節點後面添加序號
//3:Ephemeral和Sequence,即,短暫且自動添加序號
//zk.WorldACL(zk.PermAll)//控制訪問權限模式
var flag int32 =1
_, err := conn.Create(registerPath, zkVal, flag, zk.WorldACL(zk.PermAll))
if err != nil {
fmt.Println("Create Err:", err)
time.Sleep(time.Second)
continue
}
}
time.Sleep(10 * time.Second)
}
}()
}
func initConn() {
servers := strings.Split(zkservers, ",")
//注意,第二個參數爲創建之後session維持的時間,因爲session消失之後,纔會將註冊的ip地址從zk上摘除,所以不能太長,否則影響服務正常功能,一般爲1s
connZK, _, err := zk.Connect(servers, time.Second*60)
if err != nil {
panic(err)
}
if conn != nil {
conn.Close()
}
conn = connZK
}
//獲取zk結點中的配置信息,比如超時時間等
func GetConf(path string) (string, error) {
ret, _, err1 := conn.Get(path)
if err1 != nil {
fmt.Println("Get Err:", err1)
return "", err1
}
return string(ret), nil
}
//獲取zk結點下,註冊的機器的ip信息
func GetBatchConf(path string) (map[string]string, error) {
ret := make(map[string]string)
keys, _, err1 := conn.Children(path)
if err1 != nil {
return ret, err1
}
for _, key := range keys {
newPath := path + "/" + key
val, _, err := conn.Get(newPath)
if err != nil {
continue
}
ret[key] = string(val)
}
return ret, nil
}
func main() {
SetZkServers("zk服務起地址信息ip:端口,例如:10.0.0.18:3333", testlisten)
Register("/testzk","5555")//註冊的路徑和端口
conf,_ := GetConf("/testzk")
batchConf, _ :=GetBatchConf("/testzk")
fmt.Println("conf:", conf)
fmt.Println("batchConf:", batchConf)
time.Sleep(time.Minute * 60 * 24 * 365 * 100)
}