03-websocket并发发送消息出错

这篇具有很好参考价值的文章主要介绍了03-websocket并发发送消息出错。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

03-websocket并发发送消息出错

前言:本文主要介绍在spring框架下使用spring集成的websocket,并发发送消息,演示websocket消息在并发场景下出错

1 环境搭建

这里,我是用的是spring集成的websocket,当然也可以使用javax.websocket,都可以达到效果。

1.1 总体流程介绍

  1. 使用spring集成的websocket,参考上一篇文章的内容,这是文章的链接地址:https://blog.csdn.net/weixin_43716785/article/details/135713471?spm=1001.2014.3001.5502

  2. 书写controller,调用里面的方法实现并发 发送消息

    controller里面的代码说明:

    变量i1

    final int i1 = 50表示给每个客户端发送50条消息

    参数:@RequestParam Integer count

    先用apiPost7建立3个或者更多ws链接,指定id为1,2,3,这样方便测试;

    在调用测试接口时,传一个count值,使用for循环,1~count的值就是客户端对应的Id(我设定的是scanPoint,一样的)

    然后根据循环体的值,新开一个线程,并发给指定的客户端的发送消息

    import lombok.extern.slf4j.Slf4j;
    import org.example.service.MyWebSocketHandler;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.io.IOException;
    
    /**
     * 类描述
     *
     * @author cjia
     * @date 2024/1/21 上午 11:34
     */
    @Slf4j
    @RestController
    public class TestController {
        @Autowired
        private MyWebSocketHandler webSocketHandler;
    
        /**
         * 每个session 50条消息
         */
        final int i1 = 50;
    
        /**
         * 先用apiPost7建立几个连接,我建立的3个,对应的id分别是1,2,3
         * 这样的话,count传值3,就可以模拟给这3个客户端发消息
         *
         * @param count
         * @return
         * @throws IOException
         */
        @GetMapping("/test-01")
        public Object test(@RequestParam Integer count) {
            for (int j = 0; j < i1; j++) {
                for (int i = 1; i <= count; i++) {
                    int finalI = i;
                    new Thread(()->{
                        try {
                            //handler提供的发送消息的方法
                            webSocketHandler.sendMessage(String.valueOf(finalI), "测试消息" + finalI);
                            log.info("================>当前线程返回:{}", Thread.currentThread().getName());
                        } catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }).start();
    
                }
            }
            //返回的结果,不用在意
            return  "{'code':200,'message':'接口调用成功!'}";
        }
    
    }
    
  3. 先使用apiPost7建立3个websocket连接,如图

    websockethandler 并发,websocket,websocket

2 调用接口,并发发送wbsocket消息

websockethandler 并发,websocket,websocket

控制台结果截图

websockethandler 并发,websocket,websocket

看到了吗?是不是很熟悉的错误提示

The remote endpoint was in state [TEXT_PARTIAL_WRITING] which is an invalid state for called method

顺手翻译下:远程端点处于状态 [TEXT_PARTIAL_WRITING],这对于被调用方法来说是无效状态

3 websocket消息在并发场景下出错的原因解析

3.1 并发场景下很难调试,我这里先给出发送单条消息的流程

先给出流程图,可以看出最终还是调用的tomcat的方法发送消息

StandardWebSocketSession的sendxxx方法 中通过 getNativeSession().getBasicRemote().sendText(message.getPayload(),

message.isLast())来发送消息。注意:getBasicRemote()和getAsyncRemote()是不一样的,getAsyncRemote()是支持异步或者并发的,

getBasicRemote()是同步的,那,那为什么spring不用这个方法呢?还是先埋个坑,后面在填,这里主要介绍整个发送消息的流程,有一个整体的印象即可

websockethandler 并发,websocket,websocket


这个是tomcat最终消息发送流程图

websockethandler 并发,websocket,websocket


下面是debug的截图

注意:下面是一大波图

3.1.1 我这里通过服务端收到消息,直接返回该消息,来调用发送发消息的api,也可以单独写接口来发送单条消息

websockethandler 并发,websocket,websocket

3.1.2 进入自定义handler发送消息的方法

websockethandler 并发,websocket,websocket

3.1.3 进入spring的AbstractWebSocketSession

在 sendMessage方法中,根据消息的类型来确定需要调用的发送方法(我使用的消息类型是Textmessage)

websockethandler 并发,websocket,websocket

3.1.4 进入StandardWebSocketSession(AbstractWebSocketSession的实现类)

通过sendTextMessage方法调用tomcat的websocket的发送方法,这里往后,就进入tomcat的依赖中

websockethandler 并发,websocket,websocket

3.1.5 进入tomcat的WsRemoteEndpointBasic

通过sendXX发送消息

websockethandler 并发,websocket,websocket

3.1.6 发送消息前的状态机进行状态校验

websockethandler 并发,websocket,websocket

3.1.7 状态校验通过,修改当前的状态值,不通过,抛出异常

websockethandler 并发,websocket,websocket

websockethandler 并发,websocket,websocket

websockethandler 并发,websocket,websocket

3.1.7 发送消息

websockethandler 并发,websocket,websocket

3.1.8 状态复位,准备下一次消息发送

websockethandler 并发,websocket,websocket

3.2 并发场景下出错的原因

通过上面的tomcat最终消息发送流程图,可以看出,WsRemoteEndpointImplBase内部有一个维护状态的状态机,通过状态机的状态来判断是否可以发送消息,但是这个状态明显是线程不安全的,因为还未来得及状态复位的时候,这个时候来了一条消息,又需要给当前的客户端发送一条消息,但是由于上一条消息还未发送完,状态还未来得及复位,所以后面消息就会发送失败,直到状态复位之后,才能发送消息给客户端

websockethandler 并发,websocket,websocket

4 总结

由于tomcat的websocket的内部的状态机,每次在发送消息的时候,都会进行状态校验,但是并发场景下,当状态来不及复位的时候,就会发送消息异常。我感觉是不是websocket本身只支持同时接收一条消息,就像打电话一样,你一次只能接一个人的电话,当你在通话中的时候,另一个人打进来,就提示正在通话中,相当于通话失败。


后面会继续更新解决方案的文章文章来源地址https://www.toymoban.com/news/detail-834382.html

到了这里,关于03-websocket并发发送消息出错的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端如何使用WebSocket发送消息

    WebSocket是一种在Web应用程序中实现实时双向通信的协议。相比传统的HTTP协议,WebSocket提供了更高效、更快速的双向通信方式,可以在客户端和服务器之间实时交换数据。本文将详细介绍前端如何使用WebSocket发送消息,包括创建WebSocket对象、监听WebSocket事件、发送消息以及关闭

    2024年02月11日
    浏览(40)
  • Java 实现使用 Websocket 发送消息

    需求背景:之前做了个楼栋房间数量出租了多少,需要在数据大屏上实时展示 解决方案:以切面拦截出租接口,当有房间出租时重新查询相关数据,封装好用websocket实时传送前端展示 提示:以下是本篇文章正文内容,下面案例可供参考 WebSocket 是一种在单个TCP连接上进行全双

    2024年03月27日
    浏览(43)
  • JAVA 使用WebSocket发送通知消息

    注: 1、jdk必须要1.8及以上 2、项目若有接口拦截过滤,WebSocket接口必须要配置拦截,使其可以验证通过 WebSocket 业务类 发送消息的方法 前端代码

    2024年02月11日
    浏览(52)
  • 【前端系列】前端如何使用websocket发送消息

    今天来学习一下前端如何使用websocket发送消息 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它可以让客户端和服务器之间进行实时的双向通信。与传统的 HTTP 请求不同,WebSocket 使用了一个长连接,在客户端和服务器之间保持持久的连接,从而可以实时地发送和接

    2024年02月11日
    浏览(47)
  • qt websocket 通讯实现消息发送接收

    websocket 是基于 TCP socket 之上的应用层, 解决 HTML 轮询连接的问题,实现客户端与服务端长连接, 实现消息互相发送,全双工。 服务端, 使用 QT 教程demo chatserver.h chatserver.cpp main.cpp 客户端 clientwidget.h clientwidget.cpp websocketclient.h websocketclient.cpp

    2024年02月15日
    浏览(46)
  • 前端使用websocket发送消息,建立连接(详细)。【前端】

    序言 今天来学习一下前端如何使用websocket发送消息 1.1 什么是WebSocket WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它可以让客户端和服务器之间进行实时的双向通信。与传统的 HTTP 请求不同,WebSocket 使用了一个长连接,在客户端和服务器之间保持持久的连接,从

    2024年02月04日
    浏览(43)
  • java连接websocket服务器并发送消息

    一、用python快速启动一个websocker服务器 二、使用java连接并发送消息

    2024年02月11日
    浏览(47)
  • 【通用消息通知服务】0x3 - 发送我们第一条消息(Websocket)

    项目地址: A generic message notification system[Github] Websocket Connection Pool Websocket Provider websocket接口 结果截图

    2024年02月10日
    浏览(40)
  • Spring定时任务+webSocket实现定时给指定用户发送消息

    生命无罪,健康万岁,我是laity。 我曾七次鄙视自己的灵魂: 第一次,当它本可进取时,却故作谦卑; 第二次,当它在空虚时,用爱欲来填充; 第三次,在困难和容易之间,它选择了容易; 第四次,它犯了错,却借由别人也会犯错来宽慰自己; 第五次,它自由软弱,却把

    2024年02月07日
    浏览(51)
  • websocket 发送的消息超过默认限制就会自动断开连接

    近整理了一波电子书籍资料,包含《Effective Java中文版 第2版》《深入JAVA虚拟机》,《重构改善既有代码设计》,《MySQL高性能-第3版》,《Java并发编程实战》等等 获取方式: 关注公众号并回复 电子书 领取,更多内容持续奉上 springboot集成websocket需要三步: 添加依赖  添加配

    2024年02月12日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包