samuel的zk客户端在建立连接时,会返回3个参数,其中第二个参数可用于检测连接的建立状态,仅当state等于StateHasSession时,客户端才是可用的。
func Connect(servers []string, sessionTimeout time.Duration, options ...connOption) (*Conn, <-chan Event, error)
type State
type State int32
const (
StateUnknown State = -1
StateDisconnected State = 0
StateConnecting State = 1
StateAuthFailed State = 4
StateConnectedReadOnly State = 5
StateSaslAuthenticated State = 6
StateExpired State = -112
StateConnected = State(100)
StateHasSession = State(101)
)
网上的示例通常忽略第二个参数,但是因为zk客户端内部会另起一个goroutine去建立连接,所以当Connect返回时连接并没有建立成功,这里返回的error为空也不代表连接已经建立。而有些应用场合需要确定连接是否已成功建立,例如在下面的一个zk查询客户端程序中,需要等待连接建立成功之后才向终端输出命令提示符“>”。
package main
import (
"fmt"
"github.com/samuel/go-zookeeper/zk"
"log"
"time"
)
func main() {
var err error
var conn *zk.Conn
var evtchan <-chan zk.Event
var evt zk.Event
conn, evtchan, err = zk.Connect([]string{"127.0.0.1:2181"},
time.Second*5,
zk.WithLogInfo(false),
)
if err != nil {
log.Fatalf("zk connect error:%v\n", err.Error())
return
}
log.Printf("=====> before loop check <=======")
//check the zkclient's state until it's the state of "StateHasSession"
for {
evt = <-evtchan
log.Printf("zk event:%s %s\n", evt.Type, evt.State)
if evt.State == zk.StateHasSession {
break
}
}
for {
var children []string
var cmdstr string
fmt.Print(">")
fmt.Scanln(&cmdstr)
fmt.Printf("%s\n", cmdstr)
children, _, err = conn.Children(cmdstr)
if err != nil {
fmt.Printf("%v\n", err.Error())
continue
}
for index, child := range children {
fmt.Printf("[%d]%s\n", index, child)
}
var byteArr []byte
byteArr, _, err = conn.Get(cmdstr)
if err != nil {
fmt.Printf("%v\n", err.Error())
continue
}
fmt.Printf("%s\n", string(byteArr))
}
}
可以看到,zk的整个连接建立过程是在打印"before loop check"之后执行的,而当客户端达到“StateHasSession”状态后,才输出命令提示符“>”,等待输入命令。
[[email protected] hippo]# go run example.go
2020/11/03 23:24:11 =====> before loop check <=======
2020/11/03 23:24:11 zk event:EventSession StateConnecting
2020/11/03 23:24:11 zk event:EventSession StateConnected
2020/11/03 23:24:11 zk event:EventSession StateHasSession
>