当前位置: 首页 > news >正文

消息推送的三种常见方式:轮询、SSE、WebSocket

摘要:本文介绍消息推送的三种常见方式轮询(定时请求,易增负担)与长轮询(阻塞请求至有数据 / 超时,减少请求)、SSE(HTTP 单向实时传输,纯文本、自动重连)、WebSocket(全双工通信,含客户端 API 与 Java 服务端 Endpoint 实现)。

1. 消息推送常见方式

                    轮询                长轮询                SSE                Websocket

1.1 轮询方式

轮询

  • 工作机制:浏览器按照指定的时间间隔,不断向服务器发送 HTTP 请求(如示例中的 GET/poll)。服务器收到请求后,会实时返回数据给浏览器。
  • 特点不管服务器有没有新数据,浏览器都会定时发请求这种方式可能导致请求过于频繁即便服务器无数据更新,也会产生大量请求,增加服务器和网络的负担,而且如果轮询间隔设置不合理,还可能出现数据更新的延迟(如图中 “延迟” 所示)。

长轮询

  • 工作机制:浏览器发送 Ajax 请求(如示例中的 GET/lpoll)后,服务器接收到请求会 “阻塞” 该请求。也就是说,服务器不会立即返回响应,而是等待有数据更新或者请求超时的时候,才会把数据返回给浏览器。
  • 特点:相比轮询,长轮询减少了不必要的请求次数。只有当有数据变化或者超时,服务器才会响应,能在一定程度上降低服务器和网络的压力,也能更及时地获取数据更新(只要数据更新在超时前发生)。

简单来说,轮询是 “定时问”,长轮询是 “问了等,有了才回”,二者在请求频率、资源消耗和数据实时性等方面存在差异,可根据实际场景选择使用。



1.2 SSE 技术

服务器发送事件(Server-Sent Events)是一种用于从服务器到客户端的 单向、实时 数据传输技术,基于 HTTP协议实现。

    它有几个重要的特点:

    1. 单向通信:SSE 只支持服务器向客户端的单向通信,客户端不能向服务器发送数据。
    2. 文本格式:SSE 使用 纯文本格式 传输数据,使用 HTTP 响应的 text/event-stream MIME 类型。(数据流信息)
    3. 保持连接:SSE 通过保持一个持久的 HTTP 连接,实现服务器向客户端推送更新,而不需要客户端频繁轮询。
    4. 自动重连:如果连接中断,浏览器会自动尝试重新连接,确保数据流的连续性。

    SSE 数据格式

    SSE 数据流的格式非常简单,使用 event 指定事件名称,用于区分不同类型的消息。每个事件使用 data 字段,作为消息主体,事件以两个换行符结束。还可以使用 id 字段来标识事件,并且 retry 字段可以设置重新连接的时间间隔。

    event: 事件名\n    // 可选,用于区分不同类型的消息
    data: 消息内容\n    // 必选,消息主体(可多行,每行以 data: 开头)
    id: 消息ID\n       // 可选,用于客户端记录最后接收的消息ID(重连时可通过 Last-Event-ID 头传递)
    retry: 重连时间(毫秒)\n  // 可选,指定客户端重连间隔
    \n  // 空行表示一条消息结束

    示例格式如下:

    data: Third message\n
    id: 3\n
    \n
    retry: 10000\n
    data: Fourth message\n
    \n

    1.3 WebSocket

    WebSocket 是一种网络通信协议,它通过在单个、长期的连接上提供全双工(双向)的通信通道,来解决 HTTP 协议在实时通信方面的不足。

    1.3.1 原理解析

    这张图解析了 WebSocket 连接的建立过程及原理,可分为以下几个部分:

    连接建立阶段(基于 HTTP 协议升级)

    1. 客户端请求:客户端向服务器发送一个特殊的 HTTP 请求,请求中包含 Upgrade: websocket 等头信息,表明希望将连接从 HTTP 协议升级为 WebSocket 协议。下方 “请求数据” 框里展示了具体的请求内容,像 GET ws://localhost/chat HTTP/1.1(指定 WebSocket 连接的地址)、Connection: Upgrade(表示要升级连接)、Upgrade: websocket(明确升级到 WebSocket 协议)等。
    2. 服务器响应:服务器收到请求后,返回 HTTP/1.1 101 Switching Protocols 响应,确认协议升级。下方 “响应数据” 框里呈现了响应的具体内容,包含 Upgrade: websocketConnection: Upgrade 等,表明已切换到 WebSocket 协议。

    数据传输阶段(基于 WebSocket 协议)

    当协议升级完成后,客户端和服务器就可以基于 WebSocket 协议进行全双工通信了,双方能相互主动发送数据(图中 “发送数据” 的双向箭头体现了这一点),不再受 HTTP 协议请求 - 响应模式的限制,适合实时性要求高的场景,比如在线聊天、实时数据推送等。

    1.3.2 客户端API


    1. WebSocket 对象创建

    代码示例:let ws = new WebSocket(URL);

    作用:在浏览器中创建一个 WebSocket 实例,用于和服务器建立 WebSocket 连接。

    URL 说明:

    • 格式为 协议://ip地址/访问路径
    • 其中协议名称为 ws(若为加密连接则用 wss,类似 HTTPS),ip地址 是服务器的地址,访问路径 是 WebSocket 服务在服务器上的具体路径。

    2. WebSocket 对象相关事件

    这部分通过表格列出了 WebSocket 实例常用的事件及对应的事件处理程序和描述:

    事件事件处理程序描述
    openws.onopen当客户端与服务器成功建立 WebSocket 连接时触发该事件。
    messagews.onmessage当客户端接收到服务器发送的数据时触发该事件。
    closews.onclose当 WebSocket 连接关闭时(无论是客户端主动关闭,还是服务器关闭,或者连接异常断开)触发该事件。

    3. WebSocket 对象提供的方法

    这部分介绍了 WebSocket 实例的方法:

    方法名称描述
    send()客户端通过调用 WebSocket 实例的 send() 方法,向服务器发送数据。

    1.3.3 代码实现
    <script>let ws = new WebSocket("ws://localhost/chat");ws.onopen = function() {};ws.onmessage = function(evt) {// 通过 evt.data 可以获取服务器发送的数据};ws.onclose = function() {};
    </script>

    1. 创建 WebSocket 实例

    let ws = new WebSocket("ws://localhost/chat");
    
    • 使用 new WebSocket() 构造函数创建一个 WebSocket 连接对象。
    • 参数 "ws://localhost/chat" 是 WebSocket 服务器的地址,ws:// 表示使用 WebSocket 协议(如果是加密的 WebSocket 连接,使用 wss://),localhost 是本地服务器地址,/chat 是具体的 WebSocket 端点路径,用于标识要连接的服务。

    2. 处理连接建立事件(onopen

    ws.onopen = function() {// 连接成功建立后执行的代码
    };
    
    • onopen 是 WebSocket 对象的一个事件处理属性。
    • 当客户端与 WebSocket 服务器成功建立连接时,这个函数会被调用。通常可以在这里执行一些连接成功后的操作,比如向服务器发送初始化消息等。

    3. 处理消息接收事件(onmessage

    ws.onmessage = function(evt) {// 通过 evt.data 可以获取服务器发送的数据
    };
    
    • onmessage 事件在客户端接收到服务器发送的数据时触发。
    • 回调函数的参数 evt 包含了服务器发送的数据,通过 evt.data 可以获取到具体的数据内容,数据可以是字符串、Blob 或者 ArrayBuffer 等格式,这里通常需要根据实际情况对数据进行解析和处理,比如展示聊天消息、更新实时数据等。

    4. 处理连接关闭事件(onclose

    ws.onclose = function() {// 连接关闭后执行的代码
    };
    

    • onclose 事件在 WebSocket 连接关闭时触发,不管是客户端主动关闭还是服务器关闭连接,或者连接异常断开,这个函数都会被调用。可以在这里进行一些资源清理、提示用户连接已关闭或者尝试重新连接等操作。

    1.3.4 服务端API

    Java WebSocket 应用由一系列的 Endpoint 组成。Endpoint 是一个 Java 对象,代表 WebSocket 链接的一端,对于服务端,我们可以视为处理具体 WebSocket 消息的接口。

    Endpoint 的定义方式

    我们可以通过两种方式定义 Endpoint

    • 第一种是编程式,即继承类 javax.websocket.Endpoint 并实现其方法。
    • 第二种是注解式,即定义一个 POJO,并添加 @ServerEndpoint 相关注解。

    Endpoint 的生命周期

    Endpoint 实例在 WebSocket 握手时创建,并在客户端与服务端链接过程中有效,最后在链接关闭时结束。在 Endpoint 接口中明确定义了与其生命周期相关的方法,规范实现者确保生命周期的各个阶段调用实例的相关方法。生命周期方法如下:

    方法描述注解
    onOpen()当开启一个新的会话时调用,该方法是客户端与服务端握手成功后调用的方法@OnOpen
    onClose()当会话关闭时调用@OnClose
    onError()当连接过程异常时调用@OnError

    1.3.5 服务端接收和推送数据

    1.3.6 代码实现

    @ServerEndpoint("/chat")
    @Component
    public class ChatEndpoint {@OnOpen//连接建立时被调用public void onOpen(Session session, EndpointConfig config) {}@OnMessage//接收到客户端发送的数据时被调用public void onMessage(String message) {}@OnClose//连接关闭时被调用public void onClose(Session session) {}
    }

    大功告成!


    文章转载自:

    http://OtdtDGGF.qhbhg.cn
    http://K5lsf1Pm.qhbhg.cn
    http://gR1RnvZo.qhbhg.cn
    http://YZtaSuZW.qhbhg.cn
    http://0XbKzlPZ.qhbhg.cn
    http://gTkdmKBw.qhbhg.cn
    http://kcpgXHOw.qhbhg.cn
    http://HPsagtSq.qhbhg.cn
    http://AWGBCM7Y.qhbhg.cn
    http://mBo5cel1.qhbhg.cn
    http://GiV4k1s4.qhbhg.cn
    http://JIswxS3g.qhbhg.cn
    http://zlMrUlju.qhbhg.cn
    http://jeiqLL3x.qhbhg.cn
    http://uK2xysVi.qhbhg.cn
    http://xrdiq29o.qhbhg.cn
    http://1iW8AoV1.qhbhg.cn
    http://bRiTMUX2.qhbhg.cn
    http://N1LHYY1J.qhbhg.cn
    http://RHDJpaah.qhbhg.cn
    http://3wA0o9gD.qhbhg.cn
    http://QOIjw7pw.qhbhg.cn
    http://bHw8wHNR.qhbhg.cn
    http://XZfTxkf6.qhbhg.cn
    http://yhIx3ImJ.qhbhg.cn
    http://AbfKjRl0.qhbhg.cn
    http://hXc5s0kP.qhbhg.cn
    http://30AnGSwg.qhbhg.cn
    http://nAP07Y1K.qhbhg.cn
    http://IKp1Mk1O.qhbhg.cn
    http://www.dtcms.com/a/371853.html

    相关文章:

  1. 【设计模式】 原型模式
  2. Apache EnumUtils枚举工具类
  3. pycharm如何设置对应的python解释器
  4. C++逆向输出一个字符串(三)
  5. ZYNQ 定时器
  6. Java反射与动态代理学习笔记
  7. 实现 SpringBoot 程序加密,禁止 jadx 反编译
  8. Kubeadm部署Kubernetes-v1.30.1【容器运行时containerd】
  9. HOT100--Day14--543. 二叉树的直径,102. 二叉树的层序遍历,108. 将有序数组转换为二叉搜索树
  10. 监控 Linux 服务器资源
  11. HTTP原理
  12. 【WebApi】什么情况开启如何开启缓存
  13. 中国金融机构数据库2.0-许可证、机构设立、退出、失控信息2007-2023.8
  14. Spring 异常处理器:从混乱到有序,优雅处理所有异常
  15. Elasticsearch 的 translog
  16. Spring AI Tool 实现自然语言操作MySql数据库操作详解
  17. Linux内核TCP拥塞控制机制解析:从可插拔框架到Reno算法实现
  18. 源滚滚Rust全栈班v1.02 无符号整数详解
  19. 2025最新超详细FreeRTOS入门教程:第四章 FreeRTOS消息队列
  20. Rust 登堂 之 Drop 释放资源(十一)
  21. 开关电源的原理、结构和实物入门篇-超简单解读
  22. Environments
  23. 上架商品合规流程有多条,有的长,有的短,有的需要审核,校验商品的合规性
  24. 简单聊一聊js
  25. 合格齿轴工艺工程师要修炼哪些功法?
  26. LwIP入门实战 — 5 LwIP 的内存管理
  27. 【三维生成】Matrix-3D:全向可探索的三维世界生成
  28. DispatcherServlet 初始化过程:SpringMVC 的 “启动引擎” 详解
  29. Simulink中使用Test sequence单元测试
  30. 20250907-02:LangChain 架构和LangChain 生态系统包是什么