Skip to content

Conversation

@guowei-gong
Copy link
Contributor

问题描述

启动 Node 节点后停止,再次重启时出现以下 panic:

panic: sync: negative WaitGroup counter

堆栈跟踪指向 /cluster/node/node.go:473doneWait() 函数。

根因分析

问题出在 BindNodeUnbindNode 中的 addWait()/doneWait() 调用没有严格配对:

  1. addWait()doneWait() 都依赖节点状态检查 (n.getState() != cluster.Shut)
  2. 在停止/重启场景下,状态可能在两个操作之间发生变化
  3. 如果 BindNode 时状态为 ShutaddWait 被跳过),但 UnbindNode 时状态不是 ShutdoneWait 被执行),会导致 Done() 多于 Add()
  4. 另外,重复绑定同一用户会导致多次 Add,但解绑只有一次 Done

修复方案

Proxy 结构体中添加 boundUsers sync.Map 字段,用于跟踪已绑定的用户,确保 addWait/doneWait 严格配对:

  • BindNode: 使用 LoadOrStore 确保每个用户只调用一次 addWait
  • UnbindNode: 使用 LoadAndDelete 确保只有已绑定的用户才调用 doneWait

测试步骤

  1. 启动 Node 节点
  2. 等待服务完全启动
  3. 停止服务
  4. 再次启动服务
  5. 验证不再出现 sync: negative WaitGroup counter panic

影响范围

  • 仅影响 cluster/node/proxy.go
  • 不影响现有 API 或行为
  • 不影响其他模块

兼容性

  • 向后兼容,无 breaking changes
  • sync.Map 是 Go 标准库,无额外依赖

在 Proxy 中添加 boundUsers 跟踪已绑定用户,确保 BindNode/UnbindNode 中的 addWait/doneWait 调用严格配对,避免重复绑定或未绑定时解绑导致计数器不匹配
@dobyte
Copy link
Owner

dobyte commented Jan 31, 2026

非常感谢你的问题反馈,首先确定的,这个问题确实存在。但是我这里还有一个BUG,就是跨node绑定时,node未正常加入到WaitGroup中。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants