Answer the question
In order to leave comments, you need to log in
How to make a normal shutdown of the Websocket server?
My websocket server is now just waiting in a weightgroup for connections to close. I would like it to work like in net/http Shutdown
. There, the function every given amount of time (by the way, why random) knocks to close connections that have ceased to show signs of life.
pollIntervalBase := time.Millisecond
nextPollInterval := func() time.Duration {
// Add 10% jitter.
interval := pollIntervalBase + time.Duration(rand.Intn(int(pollIntervalBase/10)))
// Double and clamp for next time.
pollIntervalBase *= 2
if pollIntervalBase > shutdownPollIntervalMax {
pollIntervalBase = shutdownPollIntervalMax
}
return interval
}
timer := time.NewTimer(nextPollInterval())
defer timer.Stop()
for {
if srv.closeIdleConns() && srv.numListeners() == 0 {
return lnerr
}
select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
timer.Reset(nextPollInterval())
}
}
// closeIdleConns closes all idle connections and reports whether the
// server is quiescent.
func (s *Server) closeIdleConns() bool {
s.mu.Lock()
defer s.mu.Unlock()
quiescent := true
for c := range s.activeConn {
st, unixSec := c.getState()
// Issue 22682: treat StateNew connections as if
// they're idle if we haven't read the first request's
// header in over 5 seconds.
if st == StateNew && unixSec < time.Now().Unix()-5 {
st = StateIdle
}
if st != StateIdle || unixSec == 0 {
// Assume unixSec == 0 means it's a very new
// connection, without state set yet.
quiescent = false
continue
}
c.rwc.Close()
delete(s.activeConn, c)
}
return quiescent
}
Answer the question
In order to leave comments, you need to log in
If I understood the task correctly, you need to correctly close all connections and shut down the WebSocket server.
In fact, the accurate closing of a client WebSocket connection looks like this:
- the server sends a frame with the Close type to the socket
- the client, when receiving a frame with the Close type, generates a response with the Close type
- the server waits for a response from the client with the Close type (the client confirms the closing of the connection)
- the server with you close the socket on your side, the client closes the socket on its side
. you just need to send frames with the Close type to all open sockets in a loop, wait for a response with the Close type, and then close the socket, or close the socket by timeout.
To work with websockets, I used this packagehttps://pkg.go.dev/github.com/gobwas/ws
An example of sending a frame with the Close type
closeFrame := ws.NewCloseFrame([]byte{})
// отправляем
err := ws.WriteFrame(wsconn, closeFrame)
header, err := ws.ReadHeader(wsconn)
if header.OpCode == ws.OpClose {
// клиент подтвердил закрытие, соединение можно закрывать
wsconn.Close()
}
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question