0


WebSocket开发(心跳监测)功能

前言

在之前的文章中完成了

客服对话

的Demo功能,但是现在的连接是

无限制

的长时间连接没有做

心跳

失活

超时断连

等功能,心跳的实现方法有很多种,并且

WebSocket

就提供了

ping/pong

类型的消息。

心跳的触发方式也分两种:

  • 客户端触发:如果是前端发送心跳,后端需要返回心跳,也就是ping pong的过程会有两次数据传递。
  • 服务端触发:后端来发送心跳的话,就只需要发送ping,前端不需要回应。

这两种后续的处理方式也有各自优缺点。

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

两种方式各有利弊,看具体的

应用场景

选择心跳方式是最好的,这里使用客户端触发心跳进行

Demo

实验,前端变更比较容易,服务端也不需要写定时等处理复杂的业务,只需要在收到固定消息后返回对应消息即可。

1. WebSocket心跳

客户端触发心跳的话就是在服务端的

OnMessage

事件里进行截获处理,如果是接受参数为

String

,就在之前的逻辑之上加上判断

健康检查

的逻辑,功能很简单,客户端发送了特点消息直接返回对应的消息即可。

1.1 字符串消息

WebSocket

已经设计了心跳,也就是

Ping/Pong

,这个功能可以到达检测链接是否可用,但是如果要携带数据还是需要自己用

字符串

对象

的消息类型进行实现。

代码如下:

@OnMessagepublicvoidonMessage(String message,Session session,@PathParam("clientId")String clientId){/**
         * 持久化
         */
        baseWebSocketService.saveClientSendMsg(clientId,message,newDate());/**
         * 处理消息
         */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 =newArrayList();
                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,"接收端不在线"));}}

如果客户端发送了内容

HEALTH

则回复对应消息,我这里回复了

SUCCESS

在这里插入图片描述

但是这样有个问题,用户发送了

HEALTH

这个字符串服务端会将这个消息当作健康检查进行处理,而不是消息,这样影响了用户端的使用。

还记得之前预留了一个发送类型字段

sendType

吗,这时候这个类型就起作用了,如果要做健康检查的操作就将这个

sendType

设置为

HEALTH

,服务端根据

sendType

字段进行判断业务处理,修改一下代码:

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

1.2 Ping/Pong消息

  • Ping的协议头是0x9,Pong的协议头是0xA
  • 控制帧最大载荷为125bytes且不能拆分

服务端可以主动发生Ping/Pong消息,之前文章中写过

WebSocket

发送消息的

四种类型

,这里将上面发送

Text

文本类型换成发送

Ping

类型的消息,当然也可以发送Pong类型的消息。

代码如下:

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

Ping消息是不会被我们的OnMessage事件接收的,所以不需要特殊处理,如果是Pong消息在服务的接收是可以的。

代码如下:

@OnMessagepublicvoidonPong(PongMessage pongMessage){ByteBuffer byteBuffer = pongMessage.getApplicationData();}

具体的业务可以二次处理

2. 服务心跳

上面的心跳是对每个客户端的心跳监测,服务的心跳也要做,服务的心跳就简单了,前端定时请求

HTTP/HTTPS

协议接口。

代码如下:

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

效果如下:

在这里插入图片描述

标签: websocket java 前端

本文转载自: https://blog.csdn.net/AnNanDu/article/details/126603005
版权归原作者 余生大大 所有, 如有侵权,请联系我们删除。

“WebSocket开发(心跳监测)功能”的评论:

还没有评论