在这些情况下:
- 客户端失去与 zk 的网络连接。
- 一分钟过去了。
- 客户端重新获得与 zk 的网络连接。
我得到以下 panic :
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
这是详细的事件顺序:
- 客户端失去与 zk 的网络连接。
- 一分钟过去了。
- 客户端重新获得与 zk 的网络连接。
- goroutine A 调用
s.ReregisterAll()
->Conn()
->checkTimeout()
->reset
(bc 1 分钟过去了) ->closeAndReset()
->conn.Close()
可以阻塞一秒< - goroutine B 处理
zk.StateExpired
(zk 集群发送这个 bc 它认为这个客户端已经死了,因为它在 2 期间没有 ping。) ->reset
->closeAndReset()
->conn.Close()
导致 panic ,因为conn.Close()
已经关闭了连接的c。 shouldQuit
channel 和s.zooKeeper.getZookeeperConnection
从未被 goroutine A 调用,因为它正在阻塞第二个所以没有新的连接。
我尝试的一个简单的解决方案是在 reset
上使用互斥锁,但现在我得到的 helper.GetConnectionString()
等于空字符串。当客户端丢失然后重新获得网络连接时,避免这种崩溃并尝试进入良好状态的最佳方法是什么?修复是否应该在 github.com/samuel/go-zookeeper 中?的实现不让你关闭已经关闭的连接?
(我已经提交了这个问题 here ,但该项目似乎缺乏讨论,所以我问这个问题。)
最佳答案
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)
)
goroutine B 调用 conn.Close() 时“conn”处于什么状态?
一种可能的解决方案是在 goroutine B 中添加一个开关,如果您在 conn.StateConnecting 中,则不要调用 conn.Close()。
关于go - 重新连接后如何避免双重连接关闭?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44856087/