还用WebSocket?这才是实时消息推送的正确姿势!轻量好用~

从零搭建实时消息推送系统:基于Gotify的WebSocket实践指南 本文详细介绍了如何从零搭建基于Gotify的实时消息推送系统,利用WebSocket技术实现低延迟通信。内容涵盖Docker部署、核心功能配置、多终端集成及安全优化,适用于服务器监控、IoT设备通知等场景,是轻量级自托管消息系统的理想解决方案。 阅读详情

👉 这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 

👉这是一个或许对你有用的开源项目

国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构

RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能:

  • 多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 微服务:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本 

来源:juejin.cn/post/7325730345840066612


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

本文主要介绍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对于浏览器的兼容不是对于服务端的兼容。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

websocket和SSE有什么区别?

轮询

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

Websocket和SSE

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

SSE的官方对于SSE和Websocket的评价是

  • WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。

  • WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。

  • SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。

  • SSE默认支持断线重连,WebSocket则需要额外部署。

  • SSE支持自定义发送的数据类型。

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

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

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

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

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

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相关文档:

“

https://www.w3cschool.cn/nwfchn/wpi3cozt.html

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

“

我更建议您先把Demo跑起来,然后在看看上面这个w3cschool的SSE文档。两个配合一起看,会更方便理解些。

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

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

后端选用语言是node,框架是Express。

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

  • 第一步,建立一个index.html文件,然后复制前端代码Demo到index.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;
}
    
//判断当前浏览器是否支持SSE
let source = ''
if (!!window.EventSource) {
    source = new EventSource('http://localhost:8088/sse/');
 }else{
    thrownewError("当前浏览器不支持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");
// 可以带cookies
 res.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}`)
})

总结

  • SSE比websocket更轻

  • SSE是基于http/https协议的

  • websocket是一个新的协议,ws/wss协议

  • 如果只需要服务端向客户端推送消息,推荐使用SSE

  • 如果需要服务端和客户端双向推送,请选择websocket

  • 不论是SSE还是websocket,对于浏览器的兼容性都不错

  • 轮询是下策,很占用客户端资源,不建议使用。(不过偷懒的时候他确实方便)

  • IE不支持SSE

对了,小程序不支持SSE哦


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,“长按”或“扫描”下方二维码噢:

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
java/web/springboot项目使用WebSocket消息推送 不说废话,三言两语告诉你啥是WebSocket? 最近项目中,有消息推送和在线咨询的功能,以前也没搞过啊,有些小伙伴估计也是,那肯定要赶紧学习起来啊~ 不说废话,今天就告诉你啥是WebSocket? 1、WebSocket 与 HTTP 先说HTTP,http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能发送信息。(一句话:客户端是主动的,服务器是被动的,还需要三次握手。) 首先,WebSocket是一种网络传输协议,在2008年诞生,2011年成为国际标准。现在 阅读详情

相关推荐

从零搭建实时消息推送系统:基于WebSocket的Gotify实践指南

本文提供了一份基于WebSocket的Gotify实时消息推送系统从零搭建的完整实践指南。详细介绍了使用Docker快速部署Gotify服务器、核心概念(应用与令牌)、以及通过CURL和Python脚本发送消息的方法。文章还涵盖了HTTPS安全配置、反向代理设置,并分享了与Prometheus、CI/CD及智能家居集成的真实应用场景,帮助开发者构建私有、安全且高效的消息推送中心。

weixin_28331555的博客 320

还用 WebSocket?这才是实时消息推送的正确姿势!轻量好用~

在很久很久以前,前端一般使用轮询来进行服务端向客户端进行消息的伪推送,为什么说轮询是伪推送?因为轮询本质上还是通过客户端向服务端发起一个单项传输的请求,服务端对这个请求做出响应而已。通过不断的请求来实现服务端向客户端推送数据的错觉。并不是服务端主动向客户端推送数据。显然,轮询一定是上述三个方法里最下策的决定。首先轮询需要不断的发起请求,每一个请求都需要经过http建立连接的流程(比如三次握手,四次挥手),是没有必要的消耗。客户端需要从页面被打开的那一刻开始就一直处理请求。

程序员高级码农的博客 816

服务端实时推送技术之SSE(Server-Send Events)

服务端推送,也称为消息推送或通知推送,是一种允许应用服务器主动将信息发送到客户端的能力,为客户端提供了实时的信息更新和通知,增强了用户体验。

持之以恒 4万+

还轮询呢?这才是实时消息推送的正确姿势!轻量好用~

在很久很久以前,前端一般使用轮询来进行服务端向客户端进行消息的伪推送,为什么说轮询是伪推送?因为轮询本质上还是通过客户端向服务端发起一个单项传输的请求,服务端对这个请求做出响应而已。通过不断的请求来实现服务端向客户端推送数据的错觉。并不是服务端主动向客户端推送数据。显然,轮询一定是上述三个方法里最下策的决定。首先轮询需要不断的发起请求,每一个请求都需要经过http建立连接的流程(比如三次握手,四次挥手),是没有必要的消耗。客户端需要从页面被打开的那一刻开始就一直处理请求。

jj1245_的博客 673

开源网格生成利器Gmsh:从入门到二次开发实战指南

本文详细介绍了开源网格生成工具Gmsh,从基础概念、安装配置到核心功能实战,提供了全面的入门指南。重点阐述了其强大的二次开发能力,通过Python API实现参数化建模、边界层网格生成以及与FEniCS、OpenFOAM等求解器的集成,为有限元分析和计算流体力学仿真提供灵活高效的自动化网格划分解决方案。

weixin_29066781的博客 435

3D视觉-激光三角测量法的概述和原理

激光三角法位移测量的原理是,用一束激光以某一角度聚焦在被测物体表面,然后从另一角度对物体表面上的激光光斑进行成像,物体表面激光照射点的位置高度不同,所接受散射或反射光线的角度也不同,用。激光三角测量法是一种通过图像采集系统采集被测物表面漫反射的激光轮廓,进而基于设备已知的相对位置通过算法处理,获得被测物表面的三维轮廓数据,进而还原目标物体三维空间信息的方法。采用激光三角原理和回波分析原理进行非接触位置、位移测量的精密传感器, 广泛应用于位置、位移 、厚度、半径、形状、振动、距离等几何量的工业测量。

qq_20660115的博客 3923

使用SSE进行实时消息推送!替换WebSocket,轻量好用~

SSE(Server-Sent Events)是一种基于HTTP的单向通讯协议,支持服务端向客户端推送实时数据。相比WebSocket,SSE更轻量级,使用标准HTTP协议,兼容大多数服务器且实现简单。SSE适用于只需服务端推送的场景(如实时数据展示),而WebSocket适合需要双向通讯的场合(如聊天应用)。文章详细介绍了SSE的特性、API、使用场景,并提供了Node.js和Java的代码示例。需要注意的是,SSE不支持IE浏览器和小程序环境,在兼容性受限时可考虑使用轮询作为备选方案。

qq_27246521的博客 775

技术解析:PETR如何通过3D位置编码革新多视角3D目标检测

本文深入解析了PETR模型如何通过创新的3D位置编码技术革新多视角3D目标检测。它摒弃了DETR3D复杂的投影采样机制,通过3D坐标生成器和编码器,将3D几何信息直接注入2D图像特征,构建出3D感知特征。该方法简化了流程,提升了模型对空间关系的理解能力与训练稳定性,为自动驾驶等领域的精准感知提供了新思路。

weixin_29079743的博客 213

我有 7种 实现web实时消息推送的方案,7种!

点击上方“芋道源码”,选择“设为星标”管她前浪,还是后浪?能浪的浪,才是好浪!每天 10:33更新文章,每天掉亿点点头发...源码精品专栏原创 | Java 2021超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析网络应用框架 Netty 源码解析消息中间件 RocketMQ 源码解析数据库中间件 Sharding-JDBC 和 MyCAT 源码解析作业调度中间件 E...

芋艿V 629

《Linux运维总结:Ubuntu22.04忘记root密码解决方案》

《Linux运维总结:Ubuntu22.04忘记root密码解决方案》

东城绝神 4460

LittleFS+NANDFLASH软硬件配置详情

littleFS文件系统说明及移植过程

weixin_43200844的博客 2368

Springboot项目WebSocket消息推送

最近项目中,有消息推送的广播和在线咨询的功能,以前也没搞过啊,有些小伙伴估计也是,那肯定要赶紧学习起来啊~ 不说废话,今天就告诉你啥是WebSocket? 1、WebSocket 与 HTTP 先说HTTP,http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能发送信息。(一句话:客户端是主动的,服务器是被动的,还需要三次握手。) 首先,WebSocket是一种网络传输协议,在2008年诞生,2011年成为国际标准。现在所有浏览器都已经支持了。主要是为了解决客户端

yangyang_VV的博客 2053

【卫星语音通信】神经网络语音编解码算法:AudioDec

最新研究表明,通过深度学习模型对语音信号进行智能压缩与重建,可在12 kbps码率下实现48 kHz采样率的高保真语音还原,其主观音质评分(MOS)可达3.9分(满分4.27分),远超传统参数编码技术。这意味着未来卫星电话的通话质量有望达到CD级水准,而蜂窝网络的语音业务带宽需求可降低60%以上,为蜂窝和卫星网络中的大规模物联网语音交互铺平道路。它的诞生为神经音频编解码技术带来了一次重要升级,有助于让未来实时语音交互更流畅、更清晰,也让我们进一步体验到人工智能与音频信号处理结合所带来的创新可能性。

u011376987的博客 1473

WebSocket实时推送数据的HiChatBox实现

本文介绍如何通过WebSocket与HiChatBox组件实现低延迟、高效率的实时消息推送。涵盖连接管理、断线重连、安全认证、消息去重与UI渲染等核心机制,并结合实际架构说明其在现代聊天系统中的应用价值。

weixin_42186015的博客 1097

【Go语言实战】(9) gRPC 实现一个简单微服务

文章目录写在前面1. 安装1.1 grpc1.2 proto1.3 protobuf2. 编写代码2.1 初始化项目2.2 编写proto2.3 编写服务端2.4 实现客户端3. 演示 写在前面 这一次我们用gRPC实现获取用户的信息 1. 安装 1.1 grpc grpc的安装直接go get即可 go get google.golang.org/grpc 1.2 proto 下载proto,我是下载这个的。 然后解压出来把bin目录放在直接放在系统变量当中 1.3 protobuf 我们在

面向生活编程 3272

手把手教你学simulink实例--基于Simulink的储能系统性能评估与仿真

储能系统是现代能源体系中的关键组成部分,广泛应用于可再生能源并网、电网调峰调频、电力质量改善以及电动汽车充电等领域。为了提高储能系统的运行效率和可靠性,对其性能进行准确评估至关重要。基于MATLAB/Simulink平台,可以构建储能系统的动态模型,并通过仿真分析其在不同工况下的性能表现。本项目旨在研究储能系统的建模方法、控制策略及其性能评估指标,并通过Simulink仿真验证系统的动态特性和稳态性能。

MHD0815的博客 196

你还在使用 WebSocket 实现实时消息推送吗?

大家好,我是不才陈某~在日常的开发中,我们经常能碰见服务端需要主动推送给客户端数据的业务场景,比如数据大屏的实时数据,比如消息中心的未读消息,比如聊天功能等等。本文主要介绍SSE的使用场景和如何使用SSE。服务端向客户端推送数据的实现方案有哪几种?我们常规实现这些需求的方案有以下三种轮询websocketSSE轮询简介在很久很久以前,前端一般使用轮询来进行服务端向客户端进行消息的伪推送,为什么说轮...

码猿技术专栏 114

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: 一键群控多台电脑,这款开源神器太牛了!
下一篇: 微服务全做错了?谷歌提出新方法,成本直接暴降 90%…
公众号-芋道源码
博客等级 码龄10年 1634粉丝 377原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值