实现实时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) 服务器需要主动向客户端推送数据的场景。例如,实时通知、日志更新等。
相关文章:
实现实时Web应用,使用AJAX轮询、WebSocket、还是SSE呢??
文章目录 短轮询(Short Polling)长轮询(Long Polling)Comet “服务器推” (这玩意现在用的很少了,了解一下即可)WebSocket原理:方法:事件: SSE原理事件 总结 …...

3GPP协议入门——物理层基础(一)
1. 频段/带宽 NR指定了两个频率范围,FR1:通常称Sub 6GHz,也称低频5G;FR2:通常称毫米波(Millimeter Wave),也称高频5G。 2. 子载波间隔 NR中有15kHz,30kHz,6…...

关于Java数据结构中集合的一个小知识
在我们以后刷题的过程,我们会遇到一些奇怪的集合数据类型。 如下图 这里,我们以顺序表的集合类为例,我们看到上图函数的返回值类型有点奇怪,其实并不奇怪,也就是穿过去的参数类型是一个顺序表的集合类型,也…...

leetcode41. 缺失的第一个正数,原地哈希表
leetcode41. 缺失的第一个正数 给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。 请你实现时间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案。 示例 1: 输入:nums [1,2,0] 输出:3 解释…...

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

3.数据类型
作业系统链接 Python 是一门面向对象友好的语言,支持多种内置数据类型,包括整数(int)、浮点数(float)、布尔值(bool)、字符串(str)、列表(list&am…...

Xcode报错:No exact matches in reference to static method ‘buildExpression‘
Xcode报错1:No exact matches in reference to static method buildExpression Xcode报错2:Type () cannot conform to View 这两个报错都是因为在SwiftUI的View的Body里面使用了ForEach循环,却没有在ForEach循环闭包的内部返回视图,而是做了…...

校园安全无小事,EasyCVR视频综合管理平台助力智慧校园视频监控系统全面升级
随着信息技术的飞速发展,智慧校园作为教育信息化的重要载体,正逐步成为提升校园安全管理、优化教育资源配置、增强师生互动体验的关键手段。其中,高效、智能的视频监控系统作为智慧校园不可或缺的一部分,扮演着至关重要的角色。TS…...

通过Python代码发送量化交易信号邮件通知
量化交易利用数学模型和计算机算法来分析市场数据,并生成交易信号,本文将介绍如何使用Python编写一个简单的脚本,通过发送邮件通知量化交易信号。 开启SMTP服务 首先要在发件箱的邮件设置中,将POP3/SMPT服务开启,记录下授权密码,在本地可通过此密码登录,注意有效期和保…...

计算机毕业设计 乡村生活垃圾管理系统的设计与实现 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点…...

Qwen 2.5:阿里巴巴集团的新一代大型语言模型
Qwen 2.5:阿里巴巴集团的新一代大型语言模型 摘要: 在人工智能领域,大型语言模型(LLMs)的发展日新月异,它们在自然语言处理(NLP)和多模态任务中扮演着越来越重要的角色。阿里巴巴集…...

Element UI入门笔记(个人向)
Element UI入门笔记 将页面分割为一级菜单、二级菜单、导航栏三个部分;使用npm下载安装,使用语句npm i element-ui -s; 布局组件 el-form 用于创建和管理表单;从属性上看: :model:用于双向数据绑定,将表单…...

网络通信失败-关闭网络防火墙
0、报错描述1、分析2、解决办法 0、报错描述 在进行树莓派和PC端的网络通信的时候, 使用树莓派作为服务端,PC端作为客户端的时候,能成功通讯。 使用树莓派作为客户端,PC端作为服务端的时候,却发现通信失败。 体现在没…...
基于kolla-ansible在openEuler 22.03 SP4上部署OpenStack-2023.2
测试环境 openEuler-22.03-LTS-SP4-x86_64-dvd.iso Virtual Box,4 vCPU, 8G RAM, 50 vDisk。安装时删除/home,SWAP分区,全部空间给/目录。 目标是部署OpenStack All-In-One模式,控制节点计算节点存储节点在一台机器实现。 系统配…...
深拷贝|浅拷贝
目录 1. 深拷贝(Deep Copy) 2. 浅拷贝(Shallow Copy) 3. 深拷贝和浅拷贝的区别 4. 示例代码 浅拷贝示例 深拷贝示例 5.常用的方法 1.Java Object.clone() 方法 2.序列化与反序列化 6.Spring Boot 中的常用方法 使用 Se…...
图像处理-掩码
文章目录 一、简介二、主要用途三、代码实现四、掩码优缺点1.优点2.缺点 一、简介 在图像处理中,掩码(Mask)是一种特殊的图像,用于指定对原始图像进行操作的区域。掩码通常是二值图像(即图像上的每个像素只有两个可能…...

[2025]基于微信小程序慢性呼吸系统疾病的健康管理(源码+文档+解答)
博主介绍: ✌我是阿龙,一名专注于Java技术领域的程序员,全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师,我在计算机毕业设计开发方面积累了丰富的经验。同时,我也是掘金、华为云、阿里云、InfoQ等平台…...

react之jsx基础(1)概念和本质
文章目录 JSX 的基本概念1. **语法**2. **表达式**3. **属性**4. **子元素** JSX 的编译过程1. **转换成 JavaScript**2. **React 元素** JSX 的实际应用1. **组件定义**2. **组件嵌套** 总结 当然,以下是对 JSX 的详细讲解,包括其基本概念、语法、编译过…...

sqli-labs靶场自动化利用工具——第13关
文章目录 概要整体架构流程技术细节执行效果小结 概要 Sqli-Labs靶场对于网安专业的学生或正在学习网安的朋友来说并不陌生,或者说已经很熟悉。那有没有朋友想过自己开发一个测试脚本能实现自动化化测试sqli-labs呢?可能有些人会说不是有sqlmap&#…...

大舍传媒:尼日利亚传统新闻媒体宣传助力新兴行业蓬勃发展
大舍传媒:尼日利亚传统新闻媒体宣传助力新兴行业蓬勃发展 在全球化的浪潮下,媒体作为信息传播的重要渠道,对于促进行业发展和推动社会进步扮演着举足轻重的角色。特别是在非洲大陆上人口最多、经济最发达的国家——尼日利亚,传统…...

深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
代码随想录刷题day30
1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币,另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额,返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
git: early EOF
macOS报错: Initialized empty Git repository in /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/ remote: Enumerating objects: 2691797, done. remote: Counting objects: 100% (1760/1760), done. remote: Compressing objects: 100% (636/636…...