WebSocket development (heartbeat monitoring) function

foreword

The Demo function was completed in the previous article 客服对话, but the current connection is 无限制a long-term connection without functions such as 心跳, 失活, 超时断连and so on. There are many ways to implement heartbeat, and WebSocketit provides ping/pongtypes of messages.

There are two ways to trigger the heartbeat:

  • Client triggers:如果是前端发送心跳,后端需要返回心跳,也就是ping pong的过程会有两次数据传递。
  • Server-side trigger:后端来发送心跳的话,就只需要发送ping,前端不需要回应。

These two subsequent processing methods also have their own advantages and disadvantages.

  • Client triggers:
    • advantage
      • 灵活控制
      • 无需设置主动超时
      • 逻辑清晰
      • 服务端简单
    • shortcoming
      • 两次消息传递
      • 消息内容容易篡改
  • Server-side trigger:
    • advantage
      • 节省宽带
      • 服务端控制频率
      • 消息体固定
    • shortcoming
      • 处理逻辑复杂
      • 需要添加定时任务
      • 考虑稳定性

The two methods have their own advantages and disadvantages. The heartbeat method is the best depending on the specific 应用场景choice. Here, the client Demois used to trigger the heartbeat for experiments. After fixing the message, return the corresponding message.

1. WebSocket Heartbeat

OnMessageIf the client triggers the heartbeat , it intercepts and processes the event on the server . If the parameter is accepted String, then the judgment logic is added on top of the previous logic 健康检查. The function is very simple. The client sends a special message and directly returns the corresponding message. Can.

1.1 String messages

WebSocketHeartbeat has been designed, that is Ping/Pong, this function can reach and detect whether the link is available, but if you want to carry data, you still need to implement it with the message type of 字符串.对象

code show as below:

	@OnMessage
    public void onMessage(String message, Session session,@PathParam("clientId") String clientId){
    
    
        /**
         * 持久化
         */
        baseWebSocketService.saveClientSendMsg(clientId,message,new Date());
        /**
         * 处理消息
         */
        UserMessageModel userMessageModel = JSONObject.parseObject(message, UserMessageModel.class);
        if (userMessageModel == null){
    
    
            this.sendMessage(BaseResponseMessage.error(null,"传递参数结构异常"));
        }
        userMessageModel.setSendId(clientId);
        /**
         * 健康检查
         */
        if ("HEALTH".equals(userMessageModel.getMessage())){
    
    
            this.sendText(WebSocketHealthEnum.HEALTH.result);
            return;
        }

        /**
         * 发送消息
         */
        HashMap<String,WebSocketClient> hashMap = webSocketClientMap.get(WebSocketTypeEnum.getAcceptType(this.type));
        if (!CollectionUtils.isEmpty(hashMap)){
    
    
            if (StringUtils.isEmpty(bindKfClients.get(this.clientId))){
    
    
                List<UserMessageModel> list = new ArrayList();
                list.addAll(baseWebSocketService.queryClientSendMsg(clientId));
                list.forEach(model-> {
    
    
                    this.toCSucceed(model);
                });
            }else{
    
    
                this.toCSucceed(userMessageModel);
            }
        }else{
    
    
            baseWebSocketService.saveClientCompensateMsg(userMessageModel.getAcceptId(),message,(byte) 0);
            log.info("客户端:{} 发送消息到接受端:{} 不在线,放置到代发送列表,当前待发送列表:{}条",clientId,userMessageModel.getAcceptId());
            this.sendMessage(BaseResponseMessage.error(null,"接收端不在线"));
        }
    }

If the client sends the content HEALTH, it will reply the corresponding message, I replied hereSUCCESS

insert image description here

But there is a problem with this. After the user sends HEALTHthis string, the server will process the message as a health check instead of a message, which affects the use of the client.

Do you still remember that a send type field was reserved before sendType? At this time, this type will work. If you want to do a health check operation, sendTypeset this to HEALTH, and the server sendTypewill judge the business processing according to the field, and modify the code:

        /**
         * 健康检查
         */
        if (WebSocketHealthEnum.HEALTH.msg.equals(userMessageModel.getSendType())){
    
    
            this.sendText(WebSocketHealthEnum.HEALTH.result);
            return;
        }

1.2 Ping/Pong message

  • The protocol header of Ping is 0x9, and the protocol header of Pong is 0xA
  • The maximum payload of the control frame is 125bytes and cannot be split

The server can actively generate Ping/Pong messages. In the previous article, I wrote about WebSocketsending messages 四种类型. Here, I will change the above sending Texttext type to sending Pingtype messages. Of course, Pong type messages can also be sent.

code show as below:

        if (WebSocketHealthEnum.HEALTH.msg.equals(userMessageModel.getSendType())){
    
    
            try {
    
    
                session.getBasicRemote().sendPing(ByteBuffer.wrap("SUCCESS".getBytes()));
            } catch (IOException e) {
    
    
                throw new RuntimeException(e);
            }
            return;
        }

The Ping message will not be received by our OnMessage event, so no special processing is required. If the Pong message is received by the service, it is possible.

code show as below:

    @OnMessage
    public void onPong(PongMessage pongMessage) {
    
    
        ByteBuffer byteBuffer = pongMessage.getApplicationData();
    }

Specific business can be processed twice

2. Service Heartbeat

The above heartbeat is the heartbeat monitoring of each client, and the heartbeat of the service must also be done. The heartbeat of the service is simple, and the front end regularly requests the HTTP/HTTPSprotocol interface.

code show as below:

@Slf4j
@RestController
public class CheckHealthController {
    
    

    @GetMapping("/health")
    public ResponeApi health() {
    
    
        log.info("健康检查chatroom-IM --> 检查成功!");
        return ResponeApi.success(ResponeCodeEnum.SUCCESS,"SUCCESS");
    }
    
}

The effect is as follows:

insert image description here

Guess you like

Origin blog.csdn.net/AnNanDu/article/details/126603005