Fiber v2.38.1结合fasthttp/websocket空指针panic排查问询
问题:Fiber+fasthttp/websocket部署Heroku触发空指针Panic
使用Fiber v2.38.1(底层依赖fasthttp/websocket v1.5.0)开发的应用部署在Heroku上时出现崩溃,错误日志显示空指针解引用panic,触发位置为github.com/fasthttp/websocket.(*Conn).beginMessage函数的conn.go:479行。
已确认连接实例c不为空,但panic仍会触发;且问题仅在CloseMsg的HttpCode为418时出现——该状态码对应Heroku因空闲终止连接的意外IO场景(伴随H15错误)。
目前已通过判断HttpCode为418时不发送关闭消息的方式临时解决问题,但希望明确该panic的根本原因。
相关代码
处理关闭消息的goroutine(content_ctl.go)
// 处理关闭消息 - 来自通道 // TODO: 是否使用goroutine池? go func() { if r := recover(); r != nil { // TODO: 这样处理是否合适? fmt.Printf("从panic恢复: %v\n", r) } closeMsg := <-(*client).CloseChan // 处理关闭 log.Infof("收到关闭消息: %v", closeMsg) // 发送关闭响应 closeResp := &model.WsResp{ Status: closeMsg.HttpCode, Source: model.RespSourceConn, Msg: closeMsg.Msg, } log.Infof("连接是否为空: %v, 消息: %v\n", client.WsConn == nil, closeResp) err = client.WriteMsg(closeResp) if err != nil { log.Errorf("发送关闭消息出错: %v", closeResp) } ctl.cwm.CloseAndCleanup(client.Id) // 关闭并清理 }()
WsClient结构体及WriteMsg方法(ws_model.go)
// WebSocket客户端 type WsClient struct { WsUser ContentUuid string `json:"contentUuid"` // 内容UUID WsConn *websocket.Conn `json:"-"` // WebSocket连接 CloseChan chan *CloseMsg `json:"-"` // 关闭通道 WriteLock *sync.Mutex // 写入锁,避免并发写入WebSocket连接导致panic,写入或关闭时获取锁 } // 写入WebSocket消息,带锁 func (wsc *WsClient) WriteMsg(msg *WsResp) error { if wsc.WsConn == nil { return errutil.ErrNoConn } wsc.WriteLock.Lock() err := wsc.WsConn.WriteJSON(msg) wsc.WriteLock.Unlock() return err }
CloseMsg结构体(ws_model.go)
// 发送到关闭通道的关闭消息 type CloseMsg struct { HttpCode int `json:"httpCode"` Msg string `json:"msg"` }
补充Heroku日志
2022-10-16T05:19:03.088622+00:00 heroku[router]: at=error code=H15 desc="Idle connection" method=GET path="/api/v1/content/ws/RgPx8znal7AJb 2022-10-16T05:19:03.065493+00:00 app[web.1]: time="2022-10-16T05:19:03Z" level=info msg="error - on read: websocket: close 1006 (abnormal closure): unexpected EOF" 2022-10-16T05:20:57.758379+00:00 app[web.1]: time="2022-10-16T05:20:57Z" level=info msg="cleanup client, id = 'wscid-ee670cc5-4100-49d6-9857-8284d93a6d33'" 2022-10-16T05:20:57.758505+00:00 app[web.1]: time="2022-10-16T05:20:57Z" level=info msg="close msg received: &{418 close}"
日志显示Heroku会在连接空闲一段时间后终止连接,此时会触发418状态码的关闭消息。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

