IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> WebSocket开发(心跳监测)功能 -> 正文阅读

[网络协议]WebSocket开发(心跳监测)功能

前言

在之前的文章中完成了客服对话的Demo功能,但是现在的连接是无限制的长时间连接没有做心跳失活超时断连等功能,心跳的实现方法有很多种,并且WebSocket就提供了ping/pong类型的消息。

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

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

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

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

两种方式各有利弊,看具体的应用场景选择心跳方式是最好的,这里使用客户端触发心跳进行Demo实验,前端变更比较容易,服务端也不需要写定时等处理复杂的业务,只需要在收到固定消息后返回对应消息即可。

1. WebSocket心跳

客户端触发心跳的话就是在服务端的OnMessage事件里进行截获处理,如果是接受参数为String,就在之前的逻辑之上加上判断健康检查的逻辑,功能很简单,客户端发送了特点消息直接返回对应的消息即可。

1.1 字符串消息

WebSocket已经设计了心跳,也就是Ping/Pong,这个功能可以到达检测链接是否可用,但是如果要携带数据还是需要自己用字符串对象的消息类型进行实现。

代码如下:

	@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,"接收端不在线"));
        }
    }

如果客户端发送了内容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) {
                throw new RuntimeException(e);
            }
            return;
        }

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

代码如下:

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

具体的业务可以二次处理

2. 服务心跳

上面的心跳是对每个客户端的心跳监测,服务的心跳也要做,服务的心跳就简单了,前端定时请求HTTP/HTTPS协议接口。

代码如下:

@Slf4j
@RestController
public class CheckHealthController {

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

效果如下:

在这里插入图片描述

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-04 01:45:01  更:2022-09-04 01:45:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 22:43:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码