如何在重新获得连接时避免双重连接?

lf2*_*215 12 go apache-zookeeper apache-curator

在这些情况下:

  1. 客户端失去了与zk的网络连接.
  2. 一分钟过去了.
  3. 客户端重新获得与zk的网络连接.

我有以下恐慌:

panic: close of closed channel

goroutine 2849 [running]:
github.com/samuel/go-zookeeper/zk.(*Conn).Close(0xc420795180)
  github.com/samuel/go-zookeeper/zk/conn.go:253 47
github.com/curator-go/curator.(*handleHolder).internalClose(0xc4203058f0, 0xc420302470, 0x0)
  github.com/curator-go/curator/state.go:136 +0x8d
github.com/curator-go/curator.(*handleHolder).closeAndReset(0xc4203058f0, 0xc42587cd00, 0x1e)
  github.com/curator-go/curator/state.go:122 +0x2f
github.com/curator-go/curator.(*connectionState).reset(0xc420302420, 0x1b71d87, 0xf)
  github.com/curator-go/curator/state.go:234 +0x55
github.com/curator-go/curator.(*connectionState).handleExpiredSession(0xc420302420)
  github.com/curator-go/curator/state.go:351 +0xd9
github.com/curator-go/curator.(*connectionState).checkState(0xc420302420, 0xffffff90, 0x0, 0x0, 0xc425ed2600, 0xed0e5250a)
  github.com/curator-go/curator/state.go:318 +0x9c
github.com/curator-go/curator.(*connectionState).process(0xc420302420, 0xc425ed2680)
  github.com/curator-go/curator/state.go:299 +0x16d
created by github.com/curator-go/curator.(*Watchers).Fire
  github.com/curator-go/curator/watcher.go:64 +0x96
Run Code Online (Sandbox Code Playgroud)

这是详细的事件序列:

  1. 客户端失去了与zk的网络连接.
  2. 一分钟过去了.
  3. 客户端重新获得与zk的网络连接.
  4. goroutine A调用s.ReregisterAll()- > Conn()- > checkTimeout()- > reset(bc已过去1分钟) - > closeAndReset()- > conn.Close() 可以阻止一秒钟
  5. goroutine B句柄zk.StateExpired(zk集群发送此bc它认为这个客户端已经死了,因为它在2期间没有ping.) - > reset- > closeAndReset()- > conn.Close()这会导致恐慌,因为conn.Close()已经关闭了连接的c.shouldQuit通道s.zooKeeper.getZookeeperConnection并且从未被goroutine A调用,因为它阻止第二次,所以没有新的联系.

我试过的一个天真的解决方案就是使用互斥锁reset,但现在我已经helper.GetConnectionString()等于空字符串了.什么是避免此崩溃的最佳方法,并在客户端丢失然后重新获得网络连接时尝试进入良好状态?该修复是否应该在github.com/samuel/go-zookeeper的实现中,不让你关闭已经关闭的连接?

(我已经在这里提交了这个问题,但是这个项目在讨论方面似乎缺乏,所以我在问这个问题.)

the*_*kes 1

zk.Conn 有一个 State() 方法,它返回一个枚举“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)
)
Run Code Online (Sandbox Code Playgroud)

当goroutine B调用conn.Close()时“conn”处于什么状态?

一个可能的解决方案是向 goroutine B 添加一个开关,如果您处于 conn.StateConnecting 状态,则不会调用 conn.Close()。