mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-22 18:08:04 +00:00
fix(remotedevice): 心跳 pong 忘了 Flush —— 修「设备通道每 60 秒掉线重连」
真因(实测定位):服务端 writePong 只调 writeFrameHeader,**不 Flush**。 pong 只有两个字节,且设备空闲时没有任何别的写会顺带把 bufio 缓冲刷出去 —— 于是 pong 永远留在服务端缓冲里。 链路:客户端每 30s 发一个 ping(pingLoop)→ 服务端算出 pong 却没发出 → 客户端的读循环设的是「2 倍 ping 间隔」读超时(默认 60s)→ 每 60 秒准点 i/o timeout → 桥断开 → 3s 后重连 → 服务端 markOffline 注销 outputch, 重连后再注册。 生产日志就是这个指纹(online :20 → offline 下一分钟 :20 → 重连 :23, 连续数小时无一次例外);面板上表现为设备通道/工具凭空消失又出现, /devices 列表跟着闪。 改法:writePong 复用 writeFrame(它 Flush)。另把客户端读循环退出时的 静默 return 改成带错误与 opcode 的日志 —— 此前断线真因在设备侧完全不可见, 只能靠对端日志倒推,正是这次排查一开始卡住的地方。 回归用例 TestWSPingGetsPongWhileIdle:只发一个 ping,随后什么都不发, 要求 2s 内必须收到 pong。**反向验证过**:把修复改回 writeFrameHeader, 用例即以 `read tcp ...: i/o timeout` 失败(与生产症状一致)。
This commit is contained in:
@ -411,7 +411,12 @@ func (b *Bridge) readLoop() {
|
||||
_ = ws.writePong()
|
||||
continue
|
||||
}
|
||||
// 超时或其他错误,退出
|
||||
// 超时或其他错误,退出。
|
||||
//
|
||||
// **必须记日志**:此前这里静默 return,设备断线的真因(读超时 / 对端
|
||||
// 关闭 / 帧错)在设备侧完全不可见,只能靠对端日志倒推。
|
||||
// 2 倍 ping 间隔内的读超时通常是“心跳没人回”——查服务端 writePong 是否真发出。
|
||||
log.Printf("[devicebridge] read loop exit (opcode=%#x, close=%v): %v", opcode, isClose, err)
|
||||
return
|
||||
}
|
||||
if isClose {
|
||||
|
||||
Reference in New Issue
Block a user