实现实时Web应用,使用AJAX轮询、WebSocket、还是SSE呢??

文章目录

    • 短轮询(Short Polling)
    • 长轮询(Long Polling)
    • Comet “服务器推” (这玩意现在用的很少了,了解一下即可)
    • WebSocket
      • 原理:
      • 方法:
      • 事件:
    • SSE
      • 原理
      • 事件
    • 总结

在日常的开发中,我们经常能碰见服务端需要主动推送给客户端数据的业务场景,比如数据大屏的实时数据、新闻数据、消息中心的未读消息,聊天功能、股票走势、天气情况等等。

我们的方案大概就是轮询、WebSocket、SSE


短轮询(Short Polling)

客户端定期(例如每几秒)发送AJAX请求到服务器。服务器立即响应请求,返回当前的数据状态。客户端处理响应,然后再次发送请求。

1、可能会有大量的无效请求,因为大多数请求可能返回相同的数据。
2、延迟与轮询间隔相关,间隔越长,延迟越大。

长轮询(Long Polling)

客户端发送AJAX请求到服务器。服务器挂起请求,直到有新数据可发送或超时。服务器响应请求,客户端处理数据,然后立即发送新的请求。

1、服务器需要管理挂起的请求,这可能会增加服务器的负载。
2、如果服务器延迟响应,客户端可能会遇到超时问题。

Comet “服务器推” (这玩意现在用的很少了,了解一下即可)

基于 HTTP长连接的“服务器推”技术,Comet是轮询的一种,旨在实现更接近实时的服务器到客户端的数据推送

“服务器推”是一种很早就存在的技术,以前在实现上主要是通过客户端的套接口,或是服务器端的远程调用。在Comet出现之前,大多数Web应用程序都依赖于客户端定期轮询服务器以获取更新(例如通过AJAX)。Comet技术允许服务器在有新数据时主动推送给客户端,从而减少了不必要的轮询和延迟。

随着WebSocket等更先进的实时通信技术的出现,Comet的使用已经逐渐减少。WebSocket提供了全双工通信,且在现代浏览器中得到广泛支持,因此成为了实现实时Web应用的更佳选择。然而,在某些特定场景下,Comet仍然有其应用价值,尤其是在需要兼容旧版浏览器或特定网络环境的情况下。

Comet 应用的实现模型:

  • 长轮询(Long Polling)
  • HTTP流(HTTP Streaming)
  • iframe流(iFrame Streaming)
  • Flash XMLSocket
  • XHR multipart streaming

Comet应用的一般实现步骤:

  • 客户端初始化请求:
    客户端通过AJAX或其他技术发送请求到服务器。
  • 服务器挂起请求:
    服务器接收到请求后,如果有新数据,立即响应;如果没有新数据,服务器挂起请求。
  • 数据推送:
    当新数据到达时,服务器将数据推送到客户端。
  • 客户端处理数据:
    客户端接收到数据后,进行处理,然后根据需要重新发起请求。
  • 服务器关闭连接:
    服务器在发送完数据后关闭连接,等待下一个请求。

轮询缺点:

  • 资源消耗
    • 服务器负载:轮询要求服务器频繁地处理来自客户端的请求,即使这些请求可能不包含任何实际的数据更新,从而增加了服务器的负载。
    • 带宽浪费:每个轮询请求都需要消耗网络带宽,而大多数请求可能返回的是无用的数据(即没有更新)。
  • 延迟
    • 响应时间:轮询间隔决定了客户端感知到服务器数据更新的最大延迟。如果轮询间隔设置得太长,用户体验会受到影响;如果设置得太短,则会增加服务器和网络负担。
  • 效率低下
    • 无效请求:轮询通常会导致大量的无效请求,因为这些请求在大多数情况下不会携带新的数据。
  • 用户体验
    • 延迟和不流畅:由于轮询间隔的存在,用户可能会经历数据更新的延迟,这在需要实时反馈的应用中尤其明显。
    • 资源占用:频繁的轮询可能会导致客户端(尤其是移动设备)的CPU和电池资源消耗增加。
  • 可扩展性
    • 并发问题:随着用户数量的增加,轮询机制可能导致大量的并发请求,这对服务器来说是一个扩展性问题。
  • 实现复杂性
    • 客户端逻辑:客户端需要实现定时轮询的逻辑,这增加了客户端代码的复杂性。
    • 错误处理:轮询机制需要考虑网络错误、服务器错误等情况,并实现相应的重试逻辑。
  • 网络限制
    • 防火墙和代理问题:某些网络配置可能限制频繁的轮询请求,这可能导致轮询机制在某些环境下不可用。

WebSocket

WebSocket是一种在单个连接上进行全双工通信的协议。它允许服务器和客户端之间进行实时、双向的数据交换,而无需重新建立连接。使用ws/wss

原理:

  • 握手: WebSocket连接始于一个标准的HTTP请求,这个请求通过特殊的HTTP头(如Upgrade和Connection)请求将连接升级到WebSocket协议。
  • 持久连接: 一旦握手成功,客户端和服务器之间的连接就会保持开放,直到任意一方显式地关闭连接。
  • 数据帧: WebSocket使用帧来传输数据。每个帧代表一个消息的一部分,可以是文本或二进制数据。
  • 多路复用: WebSocket连接可以同时发送和接收多个消息,不需要为每个消息单独建立连接。

方法:

  • WebSocket.close([code[, reason]]):关闭当前链接。

    该方法用于关闭 WebSocket 连接,如果连接已经关闭,则此方法不执行任何操作;

  • WebSocket.send(data):对要传输的数据进行排队。

    该方法将需要通过 WebSocket 链接传输至服务器的数据排入队列,并根据所需要传输的数据的大小来增加 bufferedAmount 的值 。若数据无法传输(比如数据需要缓存而缓冲区已满)时,套接字会自行关闭。

事件:

使用 addEventListener() 或将一个事件监听器赋值给本接口的 oneventname 属性,来监听下面的事件,也可以直接使用onopen、onmessage、onerror、onclose

  • close: 当一个 WebSocket 连接被关闭时触发。 也可以通过 onclose 属性来设置。
  • error: 当一个 WebSocket 连接因错误而关闭时触发,例如无法发送数据时。 也可以通过 onerror 属性来设置。
  • message: 当通过 WebSocket 收到数据时触发。 也可以通过 onmessage 属性来设置。
  • open: 当一个 WebSocket 连接成功时触发。 也可以通过 onopen 属性来设置。

addEventListener写法:

// 创建WebSocket连接
const socket = new WebSocket("ws://localhost:8080");// 打开连接时触发
socket.addEventListener("open", function (event) {console.log('Connection established');// 发送消息到服务器socket.send('Hello, Server!');
});// 接收服务器消息时触发
socket.addEventListener("message", function (event) {console.log('Message from server:', event.data);
});// 关闭连接时触发
socket.addEventListener("close", function (event) {console.log('Connection closed');if (event.wasClean) {console.log('Connection closed cleanly');} else {console.log('Connection died');}
});// 错误处理
socket.addEventListener("error", function (event) {console.error('WebSocket Error:', error);
});

或者使用

// 创建WebSocket连接
var socket = new WebSocket('ws://example.com/socket');// 打开连接时触发
socket.onopen = function(event) {console.log('Connection established');// 发送消息到服务器socket.send('Hello, Server!');
};// 接收服务器消息时触发
socket.onmessage = function(event) {console.log('Message from server:', event.data);
};// 关闭连接时触发
socket.onclose = function(event) {console.log('Connection closed');if (event.wasClean) {console.log('Connection closed cleanly');} else {console.log('Connection died');}
};// 错误处理
socket.onerror = function(error) {console.error('WebSocket Error:', error);
};

WebSocket缺点:

  • 不支持跨域通信:
    默认情况下,WebSocket遵循同源策略,这意味着它不允许跨域通信。虽然可以通过CORS(跨源资源共享)或其他技术手段来实现跨域WebSocket连接,但这增加了实现的复杂性。
  • 依赖于浏览器支持:
    虽然现代浏览器普遍支持WebSocket,但在一些旧版浏览器中可能不支持。对于这些浏览器,需要实现回退方案,如长轮询或COMET。
  • 服务器负载:
    WebSocket连接是持久的,这可能导致服务器需要管理大量的并发连接,尤其是在高流量应用中,这可能会增加服务器的负载。
  • 网络中间件问题:
    代理服务器、防火墙和其他网络中间件可能不支持WebSocket协议,或者需要特殊配置才能正确处理WebSocket连接。
  • 资源消耗:
    持久的WebSocket连接可能会消耗更多的服务器资源(如内存)和带宽,尤其是在客户端数量庞大时。
  • 错误处理和重连策略:
    WebSocket连接可能会由于网络问题、服务器故障等原因而断开。客户端需要实现错误处理和自动重连策略,这增加了客户端代码的复杂性。
  • 安全性:
    WebSocket使用标准的HTTP握手,但仍然需要考虑安全措施,如使用wss://(WebSocket Secure)来确保数据传输的安全性。不当的配置可能会引入安全漏洞。
  • 消息可靠性:
    WebSocket协议本身不保证消息的可靠性。如果需要确保消息的可靠传输,需要在应用层实现额外的机制,如确认和重传机制。
  • 调试和监控:
    WebSocket的调试和监控通常比HTTP请求更复杂,因为它们是持久的连接,并且数据交换不是基于请求-响应模式的。
  • 部署和维护:
    相比于简单的HTTP服务,WebSocket服务的部署和维护可能更为复杂,尤其是在需要处理大量并发连接和高可用性要求的情况下。

SSE

Server-Sent Events(SSE)是一种服务器向客户端推送实时数据的机制,它是HTML5的一部分,用于实现服务器到客户端的单向通信。与WebSocket不同,SSE仅支持服务器向客户端推送数据,而不支持客户端向服务器推送数据。

原理

  • 单向通信: SSE允许服务器向客户端推送数据,但不支持客户端向服务器推送数据。
  • 持久连接: 一旦建立连接,服务器可以持续发送数据,直到连接被关闭。
  • 基于HTTP: SSE使用标准的HTTP协议,这使得它能够更容易地通过现有的Web基础设施工作。
  • 自动重连: 如果连接中断,浏览器会尝试自动重新连接。

事件

  • onmessage事件处理器: 当服务器发送消息时触发。event.data属性包含服务器发送的数据。
  • onerror事件处理器: 当与服务器的连接出现错误时触发。event.target.readyState属性可以用来判断连接的状态。
  • onopen事件处理器: 当与服务器的连接成功打开时触发。
  • close()方法: 关闭与服务器的连接。
    // 创建EventSource实例,连接到服务器的/events端点var eventSource = new EventSource('/events');// 监听message事件eventSource.onmessage = function(event) {var eventDiv = document.getElementById('event');eventDiv.innerHTML += event.data + '<br>';};// 监听error事件eventSource.onerror = function(error) {console.error('EventSource failed:', error);};// 监听open事件eventSource.onopen = function(event) {console.log('Connection established');};

也可以使用addEventListener方式,跟websocket的使用方法差不多。

缺点:

  • 单向通信:SSE只支持服务器到客户端的单向通信。
  • 延迟:SSE的延迟取决于服务器发送数据的频率。
  • 服务器资源消耗:服务器需要持续运行,以处理客户端的连接和数据推送。

总结

不管哪种方案都是有优点也有缺点,但是实际开发中还是根据项目选择适合的方案。

  • 短轮询适合一些简单的数据更新,不需要实时交互的应用。例如新闻网站的实时更新。
  • 长轮询需要实时数据更新,但不要求全双工通信的应用。例如,在线聊天室、股票市场更新等。
  • Comet “服务器推“ 使用场景很多,现在逐渐被WebSocket替代,但是在一些老版本的浏览器的兼容性还可以。
  • WebSocket需要实时、全双工通信的应用。例如,在线游戏、实时聊天、股票交易系统等。
  • Server-Sent Events (SSE) 服务器需要主动向客户端推送数据的场景。例如,实时通知、日志更新等。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/54270.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatisPlus 使用 IPage 分页

3.4.0之前版本 Beanpublic PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor new PaginationInterceptor();paginationInterceptor.setLimit(-1);paginationInterceptor.setCountSqlParser(new JsqlParserCountOptimize(true));r…

安全建设当中的冷门知识

今天说点有趣的话题&#xff0c;也是因为在安全建设过程中&#xff0c;安全员也不太可能都按照最理想的状态去工作&#xff0c;有资源的问题&#xff0c;有管理惰性问题&#xff0c;当然也有管理者本身决策的问题。 安全行业起步较晚&#xff0c;16年才施行网络安全法&#xff…

【JAVA】数据脱敏技术(对称加密算法、非对称加密算法、哈希算法、消息认证码(MAC)算法、密钥交换算法)使用方法

文章目录 数据脱敏的定义和目的数据脱敏的技术分类对称加密算法非对称加密算法哈希算法消息认证码&#xff08;MAC&#xff09;算法密钥交换算法 数据脱敏的技术方案实现字符替换哈希算法&#xff08;例如:SHA-3 算法&#xff09;消息认证码&#xff08;MAC&#xff09;算法(CM…

代理导致的git错误

问题&#xff1a; 今天在clone时出现如下错误&#xff1a; fatal: unable to access https://github.com/NirDiamant/RAG_Techniques.git/: Failed to connect to 127.0.0.1 port 10089 after 2065 ms: Couldnt connect to server真是让人感到奇怪&#xff01;就在前天&#…

影刀RPE学习——自动化

下载网址&#xff1a;影刀RPA - 影刀官网 (yingdao.com) 傻瓜式安装进入界面&#xff1a; 官方教程&#xff1a;影刀RPA零基础入门教程&#xff08;2024最新版&#xff09;&#xff1a;01 引入课-影刀初相识_哔哩哔哩_bilibili

Unity Hub自动安装指定版本Unity的Android开发环境

Unity开发Android环境要求SDK、DNK、JDK、Gradle版本都要对才能发布APK&#xff0c;自己去配置很容易出错。Unity Hub可以自动安装指定版本Unity的Android开发环境。 1.安装国内用的UnityHub&#xff08;我这里用的3.3.2-c6&#xff09; 2.找到对应的Unity版本 3.点击【从Unit…

职场 Death Note

场景一 测试&#xff1a;哎&#xff0c;怎么会这样呢&#xff1f;时间没到&#xff0c;他怎么就变成这个样子了呢&#xff1f;一副大惊小怪&#xff0c;整个办公室都是他的声音 开发&#xff1a;对对对&#xff0c;我代码问题&#xff0c;别BB了。 你直接说这个地方不对&#…

【Kubernetes】常见面试题汇总(十九)

目录 59.简述 Kubernetes 所支持的存储供应模式&#xff1f; 60.简述 Kubernetes CSl 模型&#xff1f; 61.简述 Kubernetes Worker节点加入集群的过程&#xff1f; 59.简述 Kubernetes 所支持的存储供应模式&#xff1f; Kubernetes 支持两种资源的存储供应模式&#xff1a…

sqlgun靶场训练

1.看到php&#xff1f;id &#xff0c;然后刚好有个框&#xff0c;直接测试sql注入 2.发现输入1 union select 1,2,3#的时候在2处有回显 3.查看表名 -1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()# 4.查看列名…

【自动驾驶】决策规划算法 | 数学基础(三)直角坐标与自然坐标转换Ⅱ

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

Karpathy认为“LLM”这个名字不准确 马斯克非常赞同

LLM 应该改名吗&#xff1f;你怎么看。在 AI 领域&#xff0c;几乎每个人都在谈论大型语言模型&#xff0c;其英文全称为 Large Language Models&#xff0c;简写为 LLM。因为 LLM 中有“Language”一词&#xff0c;因此&#xff0c;大家默认这种技术和语言密切相关。然而&…

Rust:深入浅出说一说 Error 类型

1. Rust 的错误返回机制 Rust 函数计算过程如果发生错误怎么办&#xff1f;Rust没有采取 C 的异常机制&#xff0c;而是允许直接返回错误信息。 这意味着&#xff0c;Rust 提供了错误返回机制&#xff0c;允许函数正常结束时返回计算结果&#xff0c;同时&#xff0c;如果计算…

纯小白安装pytorch(快速上手)

1.首先进入你的虚拟环境(不进入也没关系) 在anaconda prompt中打开&#xff0c;输入activate 虚拟环境2.查看自己的conda源 conda config --show channels3.清空自己的conda源 conda config --remove-key channels4.添加源 conda config --add channels https://mirrors.tu…

蓝桥杯-STM32G431RBT6(解决LCD与LED引脚冲突的问题)

一、LCD与LED为什么会引脚冲突 LCD与LED引脚共用。 网上文章是在LCD_WriteRAM、LCD_WriteRAM_Prepare、LCD_WriteReg中添加&#xff0c;但问题并没有解决。 二、使用步骤 在如下函数中加入uint16_t tempGPIOC->ODR; GPIOC->ODRtemp; LCD_Init(); void LCD_C…

动态规划:07.路径问题_珠宝的最大价值_C++

题目链接&#xff1a;LCR 166. 珠宝的最高价值 - 力扣&#xff08;LeetCode&#xff09;https://leetcode.cn/problems/li-wu-de-zui-da-jie-zhi-lcof/description/ 一、题目解析 题目&#xff1a; 解析&#xff1a; 有过做前几道题的经验&#xff0c;我们会发现这道题其实就…

IDEA甚至前进后退跳转键

1&#xff1a;快捷键设置 idea设置前进、后退快捷键_idea后退前进快捷键-CSDN博客 2&#xff1a;界面设置 IDEA添加“前进 后退 ”添加到工具栏_idea 最新社区版 左右箭头怎么设置-CSDN博客

安卓显示驱动

安卓显示驱动是用于在Android设备上提供图形和视频显示的底层软件组件。 显示驱动在Android系统中扮演着至关重要的角色&#xff0c;它们负责将图形和视频内容从系统内存传输到显示屏上。这些驱动程序确保了用户界面、图像、视频和游戏等视觉元素的正常显示。以下是关于安卓显…

SpringBoot2:web开发常用功能实现及原理解析-上传与下载

文章目录 一、上传文件1、前端上传文件给Java接口2、Java接口上传文件给Java接口 二、下载文件1、前端调用Java接口下载文件2、Java接口下载网络文件到本地3、前端调用Java接口下载网络文件 一、上传文件 1、前端上传文件给Java接口 Controller接口 此接口支持上传单个文件和…

如何准备教师资格证科目三“学科知识与教学能力”的考试与面试?(理科导向:数学/物理)

如何准备教师资格证科目三“学科知识与教学能力”的考试与面试&#xff1f;&#xff08;理科导向&#xff1a;数学/物理&#xff09; ​ 目录 收起 1 前言 1.1 自身经历 1.2 教师资格证的作用 2 知识点题型分数的分布与学习建议 2.1 科目三的知识点分数分布&#xff1a; …

MessagesPlaceholder

MessagesPlaceholder 在LangChain框架中是一个非常重要的概念&#xff0c;它主要用于在构建自然语言处理&#xff08;NLP&#xff09;应用时&#xff0c;实现消息模板的动态插入和格式化。以下是对MessagesPlaceholder的详细解释&#xff1a; 一、定义与作用 MessagesPlacehol…