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

都2024了,你还在使用websocket实现实时消息推送吗?

前言

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

本文主要介绍SSE的使用场景和如何使用SSE。

服务端向客户端推送数据的实现方案有哪几种?

我们常规实现这些需求的方案有以下三种:

  • 轮询
  • websocket
  • SSE

轮询简介

在很久很久以前,前端一般使用轮询来进行服务端向客户端进行消息的伪推送,为什么说轮询是伪推送?因为轮询本质上还是通过客户端向服务端发起一个单项传输的请求,服务端对这个请求做出响应而已。通过不断的请求来实现服务端向客户端推送数据的错觉。并不是服务端主动向客户端推送数据。显然,轮询一定是上述三个方法里最下策的决定。

轮询的缺点:

  • 首先轮询需要不断的发起请求,每一个请求都需要经过http建立连接的流程(比如三次握手,四次挥手),是没有必要的消耗。
  • 客户端需要从页面被打开的那一刻开始就一直处理请求。虽然每次轮询的消耗不大,但是一直处理请求对于客户端来说一定是不友好的。
  • 浏览器请求并发是有限制的。比如Chrome 最大并发请求数目为 6,这个限制还有一个前提是针对同一域名的,超过这一限制的后续请求将会被阻塞。而轮询意味着会有一个请求长时间的占用并发名额
  • 而如果轮询时间较长,可能又没有办法非常及时的获取数据

websocket简介

websocket是一个双向通讯的协议,他的优点是,可以同时支持客户端和服务端彼此相互进行通讯。功能上很强大。

缺点也很明显,websocket是一个新的协议,ws/wss。也就是说,支持http协议的浏览器不一定支持ws协议。

相较于SSE来说,websocket因为功能更强大。结构更复杂。所以相对比较重。

websocket对于各大浏览器的兼容性↓

SSE简介

sse是一个单向通讯的协议也是一个长链接,它只能支持服务端主动向客户端推送数据,但是无法让客户端向服务端推送消息。

长链接是一种HTTP/1.1的持久连接技术,它允许客户端和服务器在一次TCP连接上进行多个HTTP请求和响应,而不必为每个请求/响应建立和断开一个新的连接。长连接有助于减少服务器的负载和提高性能。

SSE的优点是,它是一个轻量级的协议,相对于websockte来说,他的复杂度就没有那么高,相对于客户端的消耗也比较少。而且SSE使用的是http协议(websocket使用的是ws协议),也就是现有的服务端都支持SSE,无需像websocket一样需要服务端提供额外的支持。

注意:IE大魔王不支持SSE

SSE对于各大浏览器的兼容性↓

注意哦,上图是SSE对于浏览器的兼容不是对于服务端的兼容。

websocket和SSE有什么区别?

轮询

对于当前计算机的发展来说,几乎很少出现同时不支持websocketsse的情况,所以轮询是在极端情况下浏览器实在是不支持websocketsee的下策。

Websocket和SSE

我们一般的服务端和客户端的通讯基本上使用这两个方案。首先声明:这两个方案没有绝对的好坏,只有在不同的业务场景下更好的选择。

SSE的官方对于SSEWebsocket的评价是

  • WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。
  • WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。
  • SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。
  • SSE默认支持断线重连,WebSocket则需要额外部署。
  • SSE支持自定义发送的数据类型。

Websocket和SSE分别适用于什么业务场景?

对于SSE来说,它的优点就是轻,而且对于服务端的支持度要更好。换言之,可以使用SSE完成的功能需求,没有必要使用更重更复杂的websocket

比如:数据大屏的实时数据,消息中心的消息推送等一系列只需要服务端单方面推送而不需要客户端同时进行反馈的需求SSE就是不二之选。

对于Websocket来说,他的优点就是可以同时支持客户端和服务端的双向通讯。所适用的业务场景:最典型的就是聊天功能。这种服务端需要主动向客户端推送信息,并且客户端也有向服务端推送消息的需求时,Websocket就是更好的选择。

SSE有哪些主要的API?

// 建立一个SSE链接
var source = new EventSource(url);
SSE连接状态

source.readyState

  • 0,相当于常量EventSource.CONNECTING,表示连接还未建立,或者连接断线。
  • 1,相当于常量EventSource.OPEN,表示连接已经建立,可以接受数据。
  • 2,相当于常量EventSource.CLOSED,表示连接已断,且不会重连。
SSE相关事件
  • open事件(连接一旦建立,就会触发open事件,可以定义相应的回调函数)
  • message事件(收到数据就会触发message事件)
  • error事件(如果发生通信错误(比如连接中断),就会触发error事件)
数据格式
Content-Type: text/event-stream //文本返回格式
Cache-Control: no-cache  //不要缓存
Connection: keep-alive //长链接标识

SSE:相关文档,文档入口文档入口文档入口文档入口

显然,如果直接看api介绍不论是看这里还是看官网,大部分同学都是比较懵圈的状态,那么我们下面写个demo来看一下

如何实操一个SSE链接?Demo↓

这里Demo前端使用的就是最基本的html静态页面连接,没有使用任何框架。
后端选用语言是node,框架是Express

理论上,把这两段端代码复制过去跑起来就直接可以用了。

  • 第一步,建立一个index.html文件,然后复制前端代码Demoindex.html文件中,打开文件
  • 第二步,进入一个新的文件夹,建立一个index.js文件,然后将后端Demo代码复制进去,然后在该文件夹下执行
npm init          //初始化npm       
npm i express     //下载node express框架
node index        //启动服务

在这一层文件夹下执行命令。

完成以上操作就可以把项目跑起来了

前端代码Demo

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title></head><body><ul id="ul"></ul></body><script>//生成li元素function createLi(data){let li = document.createElement("li");li.innerHTML = String(data.message);return li;}//判断当前浏览器是否支持SSElet source = ''if (!!window.EventSource) {source = new EventSource('http://localhost:8088/sse/');}else{throw new Error("当前浏览器不支持SSE")}//对于建立链接的监听source.onopen = function(event) {console.log(source.readyState);console.log("长连接打开");};//对服务端消息的监听source.onmessage = function(event) {console.log(JSON.parse(event.data));console.log("收到长连接信息");let li = createLi(JSON.parse(event.data));document.getElementById("ul").appendChild(li)};//对断开链接的监听source.onerror = function(event) {console.log(source.readyState);console.log("长连接中断");};</script>
</html>

后端代码Demo(node的express)

const express = require('express'); //引用框架
const app = express(); //创建服务
const port = 8088; //项目启动端口//设置跨域访问
app.all("*", function(req, res, next) {//设置允许跨域的域名,*代表允许任意域名跨域res.header("Access-Control-Allow-Origin", '*');//允许的header类型res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");//跨域允许的请求方式 res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");// 可以带cookiesres.header("Access-Control-Allow-Credentials", true);if (req.method == 'OPTIONS') {res.sendStatus(200);} else {next();}
})app.get("/sse",(req,res) => {res.set({'Content-Type': 'text/event-stream', //设定数据类型'Cache-Control': 'no-cache',// 长链接拒绝缓存'Connection': 'keep-alive' //设置长链接});console.log("进入到长连接了")//持续返回数据setInterval(() => {console.log("正在持续返回数据中ing")const data = {message: `Current time is ${new Date().toLocaleTimeString()}`};res.write(`data: ${JSON.stringify(data)}\n\n`);}, 1000);  
})//创建项目
app.listen(port, () => {console.log(`项目启动成功-http://localhost:${port}`)
})

效果

点击查看效果

总结

  • SSEwebsocket更轻
  • SSE是基于http/https协议的
  • websocket是一个新的协议,ws/wss协议
  • 如果只需要服务端向客户端推送消息,推荐使用SSE
  • 如果需要服务端和客户端双向推送,请选择websocket
  • 不论是SSE还是websocket,对于浏览器的兼容性都不错
  • 轮询是下策,很占用客户端资源,不建议使用。(不过偷懒的时候他确实方便)
  • IE不支持SSE
  • 小程序不支持SSE

相关文章:

都2024了,你还在使用websocket实现实时消息推送吗?

前言 在日常的开发中&#xff0c;我们经常能碰见服务端需要主动推送给客户端数据的业务场景&#xff0c;比如数据大屏的实时数据&#xff0c;比如消息中心的未读消息&#xff0c;比如聊天功能等等。 本文主要介绍SSE的使用场景和如何使用SSE。 服务端向客户端推送数据的实现…...

javaScript实现客户端直连华为云OBS实现文件上传、断点续传、断网重传

写在前面&#xff1a;在做这个调研时我遇到的需求是前端直接对接华为云平台实现文件上传功能。上传视频文件通常十几个G、客户工作环境网络较差KB/s&#xff0c;且保证上传是稳定的&#xff0c;支持网络异常断点重试、文件断开支持二次拖入自动重传等。综合考虑使用的华为云的分…...

微信小程序:实现微信小程序应用首页开发 (本地生活首页)

文章目录 小程序应用页面开发1、创建项目并配置项目目录结构配置导航栏效果三、配置 tabBar 效果四、轮播图实现4.1 创建轮播图数据容器4.2 定义一个请求轮播图数据的接口4.3 页面加载调用 数据请求接口 五、九宫格实现5.1 获取九宫格数据5.2 结构和样式的完善六、图片布局实现…...

【JavaScript】原型链和继承

文章目录 1. 原型链的概念原型原型链 2. 构建原型链构造函数与原型实例与原型链 3. 继承的实现原型链继承原型链的问题 4. 继承的最佳实践构造函数继承&#xff08;经典继承&#xff09;组合继承 5. ES6中的类和继承6. 总结 在 JavaScript 中&#xff0c;原型链和继承是构建对象…...

(二)【Jmeter】专栏实战项目靶场drupal部署

该专栏后续实战示例&#xff0c;都以该篇部署的项目展开操作。 前置条件 参考“&#xff08;一&#xff09;【Jmeter】JDK及Jmeter的安装部署及简单配置” 安装部署Jmeter&#xff0c;从文章最后下载“Postman、Rancher.ova、VirtualBox-7.0.12-159484-Win.exe、Xshell-7.0.01…...

使用 ChatGPT系统学习一门知识的技巧

如何使用 ChatGPT 高效学习一门知识&#xff1f;我探索到一种比较高效的方式&#xff1a;首先让 ChatGPT 给你一个学习提纲&#xff0c;然后以此把提纲内容逐个发给 ChatGPT&#xff0c;进行详情学习。 下面以“学习八木天线”工作原理为例说明。 以八木天线为切入点&#xff0…...

IDEA-常用插件

1、Mybatis Log Free 当我们使用mybatis log在控制台输出sql 内容&#xff0c;输出内容将语句与参数分开打印&#xff0c;还需要手动将参数替换到指定位置。 使用对应插件后&#xff0c;自动将输出内容组装成完整的可直接执行的SQL 在插件市场 查看对应名称&#xff0c;并安装。…...

揭秘:一行代码搞定.Net API高并发的烦恼

高并发下的接口请求重复提交问题 在.Net开发中&#xff0c;我们经常遇到用户疯狂点击同一按钮&#xff0c;或者服务响应慢时重复发送请求&#xff0c;导致数据重复添加或混乱。这不仅浪费资源&#xff0c;更会得到错误的业务结果。如何高效解决这一普遍问题呢&#xff1f; 常规…...

SpringBoot的 8 个优点

目录 1、简化配置 2、快速开发 3、微服务支持 4、内嵌服务器 5、健康监测 6、热部署 7、自动化管理 8、社区支持和生态系统 SpringBoot 是一个基于 Spring 框架的快速开发框架&#xff0c;它通过提供一系列的自动配置、约定优于配置、快速集成等功能&#xff0c;简化了…...

Spark中多分区写文件前可以不排序么

背景 Spark 3.5.0 目前 Spark中的实现中&#xff0c;对于多分区的写入默认会先排序&#xff0c;这是没必要的。可以设置spark.sql.maxConcurrentOutputFileWriters 为大于0来避免排序。 分析 这部分主要分为三个部分: 一个是V1Writes规则的重改; 另一个是FileFormatWriter中…...

突破编程_C++_面试(变量与常量)

面试题 1 &#xff1a; C 中的变量存储类别有哪些&#xff0c;并简要描述它们的特点&#xff1f; 在C中&#xff0c;变量的存储类别决定了变量的生命周期和可见性。以下是C中的几种变量存储类别及其特点&#xff1a; 自动存储期 也称为局部存储类别。这类变量在函数或代码块…...

k8s的一些关键信息(归类摘抄,非提炼)

零&#xff1a;举例说明 当用户提交一个 Deployment 对象到 Kubernetes 集群时&#xff0c;控制平面的 API Server 接收到该请求&#xff0c;并将其转发给 Controller Manager。Controller Manager 中的 Deployment Controller 监听到该请求&#xff0c;并根据用户定义的配置信…...

海外媒体发稿:8个提升影响力的日韩地区媒体发稿推广策略-华媒舍

在今天的数字化时代&#xff0c;媒体发稿推广成为企业和个人增加影响力的重要方式。特别是在日韩地区&#xff0c;这个拥有庞大媒体市场和活跃社交媒体用户的地区&#xff0c;正确的推广策略将对影响力的提升起到关键作用。我们将介绍8个提升影响力的日韩地区媒体发稿推广策略。…...

面试官:能不能给 Promise 增加取消功能和进度通知功能... 我:???

扯皮 这段时间闲着没事就去翻翻红宝书&#xff0c;已经看到 Promise 篇了&#xff0c;今天又让我翻到两个陌生的知识点。 因为 Promise 业务场景太多了自我感觉掌握的也比较透彻&#xff0c;之前也跟着 Promise A 的规范手写过完整的 Promise&#xff0c;所以这部分内容基本上…...

详解MySQL增删查改

众所周知&#xff0c;MySQL是非常重要的数据库语言&#xff0c;下面我们来回顾一下mysql的增删查改吧 MySQL创建数据库&#xff1a; CREATE DATABASE 数据库名;MySQL删除数据库&#xff1a; DROP DATABASE <database_name>; --直接删除&#xff0c;不检查是否存在 DROP…...

Mysql开启bin-log日志

目录 一、安装配置 二、mysqlbinlog命令 一、安装配置 yum -y install mariadb mariadb-server#安装mysql数据库#默认配置文件/etc/my.cnfvim /etc/my.cnflog-binmariadb-bin #开启二进制日志 systemctl restart mariadb#会在/car/lib/mysql/产生二进制日志文件&#xff0…...

Java:性能优化细节01-10

Java&#xff1a;性能优化细节01-10 在Java程序开发过程中&#xff0c;性能优化是一个重要的考虑因素。常见的误解是将性能问题归咎于Java语言本身&#xff0c;然而实际上&#xff0c;性能瓶颈更多地源于程序设计和代码实现方式的不当。因此&#xff0c;培养良好的编码习惯不仅…...

CVE-2022-24652 漏洞复现

CVE-2022-24652 开题 后台管理是thinkphp的&#xff0c;但是工具没检测出漏洞。 登陆后界面如下&#xff0c;上传头像功能值得引起注意 这其实就是CVE-2022-24652&#xff0c;危险类型文件的不加限制上传&#xff0c;是文件上传漏洞。漏洞路由/user/upload/upload 参考文章&a…...

LeetCode、338. 比特位计数【简单,位运算】

文章目录 前言LeetCode、338. 比特位计数【中等&#xff0c;位运算】题目链接与分类思路位运算移位处理前缀思想实现 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java…...

借助Aspose.BarCode条码控件,C# 中的文本转 QR 码生成器

二维码用于在较小的空间内存储大量数据。它们易于使用&#xff0c;可以通过智能手机或其他设备扫描来打开网站、观看视频或访问其他编码信息。在这篇博文中&#xff0c;我们将学习如何使用 C# 以编程方式生成基于文本的 QR 码。我们将提供分步指南和代码片段&#xff0c;帮助您…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

大数据学习栈记——Neo4j的安装与使用

本文介绍图数据库Neofj的安装与使用&#xff0c;操作系统&#xff1a;Ubuntu24.04&#xff0c;Neofj版本&#xff1a;2025.04.0。 Apt安装 Neofj可以进行官网安装&#xff1a;Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...