lesismal / nbio

Pure Go 1000k+ connections solution, support tls/http1.x/websocket and basically compatible with net/http, with high-performance and low memory cost, non-blocking, event-driven, easy-to-use.
MIT License
2.17k stars 153 forks source link

How to run a worker that sends ping/pong as a text message like pingHandler and pongHandler upgrader #394

Closed AnirudhDensityIntern closed 6 months ago

lesismal commented 8 months ago

What do you want to implement exactly? Is it for keepalive?

AnirudhDensityIntern commented 8 months ago

yes

lesismal commented 8 months ago

I think the best practice is:

  1. server side: SetReadDeadline and reply a pong message to a ping message
  2. client side: send a ping message every interval

In nbio, you need just set upgrader.KeepaliveTime = yourKeepaliveInterval then nbio will update ReadDeadline itself when receiving a message, nbio also replies a pong message to a ping message automatically. So, maybe that's all you need to do except ask the client side to send the keepalive ping messages themselves.

AnirudhDensityIntern commented 8 months ago

I want to make a dynamic ping message as text and insure that pong message as a text is received against that at particular time interval, lets say every 20 second.

lesismal commented 8 months ago

Although sending ping msg on the server-side can do that keepalive things and many people design their code like that, it's a little waste. server-side check read deadline would be better for server-side cost.

But if you want to do that:

upgrader.SetPongHandler(yourPingHandler) of course you should update read deadline by wsConn.SetReadDeadline(time.Now().Add(...)) in yourPongHandler or set upgrader.KeepaliveTime=...

and

wsConn.WriteMessage(PingMessage, []byte("your text")) in your self timer

AnirudhDensityIntern commented 7 months ago

we are set the conn.SetDeadline to 10 second and then we send the pong message inside the ping handler we getting the ping timeout in this case. when we write the message there is no error but still get the pong message timeout. this we get in close handler"reason\\\":\\\"read timeout\\\"

      func (u *userStreamImpl) pingHandler(userID uuid.UUID) func(conn *websocket.Conn, s string) {
          return func(conn *websocket.Conn, s string) {
              u.logger.Debug("websocket ping received", log.Any("userID", userID))
              err := conn.SetDeadline(time.Now().Add(10 * time.Second))
              fmt.Println(err)
              err = conn.WriteMessage(websocket.PongMessage, []byte{})
              fmt.Println(err)
              time.Sleep(8 * time.Second)
              err = conn.SetDeadline(time.Time{})
              //err = conn.WriteMessage(websocket.TextMessage, []byte("{\"hello dude\": \"jhehd\"}"))
              if err != nil {
                  u.logger.Error("websocket ping handler failed", log.Error(err), log.Any("userID", userID))
                  u.publishCloseMessage(userID, "websocket ping handler failed")
              }
          }
      }
lesismal commented 7 months ago

1st, you should reply to the ping message as soon as you receive it 2nd, you shouldn't time.Sleep(8 * time.Second) in a message handler, that will make the goroutine blocking for long, and may use out the goroutine pool.

AnirudhDensityIntern commented 7 months ago

we are using that without time.sleep we are replying that without sleep still getting read timeout error in close handler

lesismal commented 7 months ago
image
lesismal commented 7 months ago

Show me the full examples including both client and server sides that can reproduce it!

Your previous example is the wrong implementation.

AnirudhDensityIntern commented 7 months ago
func (u *userStreamImpl) pingHandler(userID uuid.UUID) func(conn *websocket.Conn, s string) {
          return func(conn *websocket.Conn, s string) {
              u.logger.Debug("websocket ping received", log.Any("userID", userID))
              err = conn.WriteMessage(websocket.PongMessage, []byte{})
              if err != nil {
                  u.logger.Error("websocket ping handler failed", log.Error(err), log.Any("userID", userID))
                  u.publishCloseMessage(userID, "websocket ping handler failed")
              }
          }
      }
AnirudhDensityIntern commented 7 months ago

we are managing only on server side to call different backend services for the broker

lesismal commented 7 months ago
func (u *userStreamImpl) pingHandler(userID uuid.UUID) func(conn *websocket.Conn, s string) {
        return func(conn *websocket.Conn, s string) {
            u.logger.Debug("websocket ping received", log.Any("userID", userID))
            err = conn.WriteMessage(websocket.PongMessage, []byte{})
            if err != nil {
                u.logger.Error("websocket ping handler failed", log.Error(err), log.Any("userID", userID))
                u.publishCloseMessage(userID, "websocket ping handler failed")
            }
        }
      }

Please provide the full example that I can run directly. That's not all the details.

github-actions[bot] commented 6 months ago

This issue is stale because it has been open for 30 days with no activity.

github-actions[bot] commented 6 months ago

This issue was closed because it has been inactive for 14 days since being marked as stale.