Go 打开的文件太多Websocket
进程留下太多打开的文件描述符。 当我这样做时:lsof-p$pid,大多数结果是(大约80%): 点2 28360根911u插座0,9 0t0 42082509 协议:TCPv6 在FD Type变为“sock”之前,它会保持关闭状态,等待一段时间。我注意到的是,这些“短袜”FD中有一些消失了,有一些永远留下来 打开的文件量以较小的波动逐渐增加,直到未达到最大1024。目前,我将允许打开的文件的最大数量设置为4096,以延长该过程的工作时间Go 打开的文件太多Websocket,go,websocket,Go,Websocket,进程留下太多打开的文件描述符。 当我这样做时:lsof-p$pid,大多数结果是(大约80%): 点2 28360根911u插座0,9 0t0 42082509 协议:TCPv6 在FD Type变为“sock”之前,它会保持关闭状态,等待一段时间。我注意到的是,这些“短袜”FD中有一些消失了,有一些永远留下来 打开的文件量以较小的波动逐渐增加,直到未达到最大1024。目前,我将允许打开的文件的最大数量设置为4096,以延长该过程的工作时间 srvTLS := &http.Server{
srvTLS := &http.Server{
Addr: utils.PortSocketTLS,
ReadTimeout: 10 * time.Second,
WriteTimeout: 15 * time.Second,
}
srvTLS.SetKeepAlivesEnabled(false)
处理程序:
func WsRoom(w http.ResponseWriter, r *http.Request) {
ws, err := websocket.Upgrade(w, r, nil, 1024, 1024)
if _, ok := err.(websocket.HandshakeError); ok {
http.Error(w, "Not a websocket handshake", 400)
return
} else if err != nil {
return
}
...other stuff
}
康涅狄格州作家
func PlayerWriter(pc *model.PlayerConn) {
ticker := time.NewTicker(utils.PingPeriod)
defer func() {
ticker.Stop()
pc.WS.Close()
}()
for {
select {
case message, ok := <-pc.Ch:
pc.WS.SetWriteDeadline(time.Now().Add(utils.WriteWait))
if !ok {
pc.WS.WriteMessage(websocket.CloseMessage, []byte{})
return
}
err := pc.WS.WriteMessage(websocket.TextMessage, message)
if err != nil {
return
}
inst := &model.PlayerLeftInstruction{}
_ = json.Unmarshal(message, inst)
if inst.Instruction == utils.UtilAFK || inst.Instruction == utils.RoomMoneyLess {
return
}
break
case <-ticker.C:
pc.WS.SetWriteDeadline(time.Now().Add(utils.WriteWait))
if err := pc.WS.WriteMessage(websocket.PingMessage, nil); err != nil {
return
}
break
}
}}
func PlayerWriter(pc*model.PlayerConn){
ticker:=time.NewTicker(utils.PingPeriod)
延迟函数(){
股票代码停止()
pc.WS.Close()
}()
为了{
挑选{
案例消息,ok:=在lsof中,键入“sock”通常表示:未接收任何内容的套接字连接。
我的代码中存在逻辑错误,在某些情况下没有关闭已建立的websocket连接。
此外,我有goroutine泄漏(但它并没有影响lsof的数量),pprof有助于检测泄漏。您使用的是什么websocket库?应用程序对每个连接的客户端使用一个文件描述符。是否有那么多连接的客户端?如果没有,则说明应用程序正在泄漏连接。在对pc.WS.Close()的两次调用之前添加日志语句
以确认应用程序正在关闭连接。可能是由于goroutines被阻止,应用程序没有关闭连接。另外,运行以检查数据竞争。@DeanElbaz Websocket此库:
func PlayerListener(pc *model.PlayerConn) {
defer func() {
if r := recover(); r != nil {
}
close(pc.Ch)
pc.Room.Leave <- pc
pc.WS.Close()
}()
pc.WS.SetReadLimit(utils.MaxMessageSize)
pc.WS.SetReadDeadline(time.Now().Add(utils.PongWait))
pc.WS.SetPongHandler(func(string) error { pc.WS.SetReadDeadline(time.Now().Add(utils.PongWait)); return nil })
for {
_, command, err := pc.WS.ReadMessage()
if err != nil {
break
}
si := model.StatusInstruction{}
json.Unmarshal(command, &si)
z := make([]byte, len(command))
copy(z, command)
switch si.Status {
case utils.PlayerLeft:
goto Exit
case utils.MoveTurn, utils.LocalTurn, utils.LocalBetFold, utils.LocalBet, utils.MoveTurnBet:
pc.Room.RoomData.GameBridger.InstCh <- z
break
...some stuff
default:
log.Printf("Unexpected command is responsed it is: %s", string(command))
goto Exit
}
}
Exit:
}