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