如果让你实现实时消息推送你会用什么技术?轮询、websocket还是sse

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

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

图片
学习就完事了

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

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

  1. 轮询

  2. websocket

  3. SSE

轮询简介

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

轮询的缺点:

  1. 首先轮询需要不断的发起请求,_每一个请求都需要经过http建立连接的流程_(比如三次握手,四次挥手),是没有必要的消耗。

  2. 客户端需要从页面被打开的那一刻开始就_一直处理请求_。虽然每次轮询的消耗不大,但是一直处理请求对于客户端来说一定是不友好的。

  3. _浏览器请求并发是有限制的_。比如Chrome 最大并发请求数目为 6,这个限制还有一个前提是针对同一域名的,超过这一限制的后续请求将会被阻塞。_而轮询意味着会有一个请求长时间的占用并发名额_。

  4. 而如果轮询时间较长,可能又_没有办法非常及时的获取数据_

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有什么区别?

轮询

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

Websocket和SSE

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

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

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

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

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

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

  5. 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:相关文档,文档入口文档入口文档入口文档入口[1]

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

demo请看下方

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

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

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

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

  1. 第一步,建立一个index.html文件,然后复制前端代码Demo到index.html文件中,打开文件

  2. 第二步,进入一个新的文件夹,建立一个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{
    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");
 // 可以带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}`)
})

效果

图片

结语

加油整起来,有什么好的建议,可以下方评论留言

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

使用 Logstash 丰富你的 Elasticsearch 文档

作者&#xff1a;来自 Elastic David Pilato 我们在上一篇文章中看到&#xff0c;我们可以使用摄取管道中的 Elasticsearch Enrich Processor 在 Elasticsearch 中进行数据丰富。 但有时&#xff0c;你需要执行更复杂的任务&#xff0c;或者你的数据源不是 Elasticsearch&#…

掌握这3种方法,mp3格式转换就是这么简单!

掌握MP3格式转换并不需要复杂的技术或专业知识。在数字化时代&#xff0c;我们有许多简单而有效的方法可以实现这一目标。无论是为了节省存储空间&#xff0c;提高音频文件的兼容性&#xff0c;还是其他需求&#xff0c;本文将介绍三种简单的方法&#xff0c;让您轻松掌握mp3格…

编程界的圣经:从Scheme到JavaScript构建你的计算思维

文章目录 适读人群目 录 《计算机程序的构造和解释》&#xff08;Structure and Interpretation of Computer Programs&#xff0c;简记为SICP&#xff09;是MIT的基础课教材&#xff0c;出版后引起计算机教育界的广泛关注&#xff0c;对推动全世界大学计算机科学技术教育的发…

掌握潮流,使用渐变色彩图标icon,打造独特风格!

渐变色图标icon非常抢眼&#xff0c;从日常使用频率最高的手机到街上随处可见的海报&#xff0c;通常色彩搭配出众&#xff0c;让人感觉很惊艳。对色彩搭配的不同理解会影响我们设计产品的最终性能。本文将带您了解在UI设计圈兴起的时尚色彩组合——什么是渐变色&#xff0c;如…

Docker进阶:深入理解 Dockerfile

Docker进阶&#xff1a;深入理解 Dockerfile 一、Dockerfile 概述二、为什么要学习Dockerfile三、Dockerfile 编写规则四、Dockerfile 中常用的指令1、FROM2、LABEL3、RUN4、CMD5、ENTRYPOINT6、COPY7、ADD8、WORKDIR9、 ENV10、EXPOSE11、VOLUME12、USER13、注释14、ONBUILD 命…

【Python】成功解决ZeroDivisionError: division by zero

【Python】成功解决ZeroDivisionError: division by zero &#x1f308; 个人主页&#xff1a;高斯小哥 &#x1f525; 高质量专栏&#xff1a;Matplotlib之旅&#xff1a;零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&#x1f448; 希望得到您的订…

ROS2从入门到精通0-2:ROS2简介、对比ROS1与详细安装流程

目录 0 专栏介绍1 什么是机器人操作系统&#xff1f;2 ROS的发展历程3 ROS2与ROS1的区别4 ROS2安装4.1 基本安装4.2 测试ROS24.2.1 测试一&#xff1a;发布者与订阅者4.2.2 测试二&#xff1a;海龟仿真器 5 常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习&#xff0c;掌…

CMake 交叉编译

想知道“魔笛手”在这里能发挥什么作用吗&#xff1f;想象一下&#xff0c;把 CMake 当做法力高强的魔笛手&#xff0c;C 的项目则是故事中的那些被魔笛手拯救的孩子。 父母要抚养一个孩子并非易事&#xff0c;营养需要面面俱到&#xff0c;保证身体健康&#xff0c;关心事无巨…

【周总结周末日常】

周总结 完成任务开发并且与前端联调通过 完成已开发功能的冒烟测试 修复测试中出现的一些数据显示问题 2024/3/10 晴 温度适宜 这周天气比上周好多了&#xff0c;最起码见到好几次太阳 周六在世纪公园溜达一会儿&#xff0c;偶尔呼吸下大自然&#xff0c;挺棒的…

wpscan专门针对wordpress的安全扫描工具

说明 WPScan是一款专门针对WordPress的漏洞扫描工具&#xff0c;它使用Ruby编程语言编写。WPScan能够扫描WordPress网站中的多种安全漏洞&#xff0c;包括WordPress本身的漏洞、插件漏洞和主题漏洞。此外&#xff0c;WPScan还能扫描类似robots.txt这样的敏感文件&#xff0c;并…

Clion attach一个linux进程进行debug

背景 手头的一段程序&#xff0c;目前已经在linux上运行了&#xff0c;我在windows上有源代码&#xff0c;想在本地debug一下&#xff0c;看看代码里复杂的流程都是怎么样运行的。 代码样例 # fileName:calculateSum.cpp #include <iostream>int main() {int num1, nu…

C++程序设计-第四/五章 函数和类和对象【期末复习|考研复习】

前言 总结整理不易&#xff0c;希望大家点赞收藏。 给大家整理了一下C程序设计中的重点概念&#xff0c;以供大家期末复习和考研复习的时候使用。 C程序设计系列文章传送门&#xff1a; 第一章 面向对象基础 第四/五章 函数和类和对象 第六/七/八章 运算符重载/包含与继承/虚函…

FX110网:在CP Markets申请出金四个多月了,没任何消息!

近期&#xff0c;本站收到一中国汇友投诉&#xff0c;称其CP Markets平台已数月无法出金&#xff0c;平台方也没有任何回应。在货币市场闯荡久了的“老鸟”就会知道&#xff0c;平台无故不给出金必定有妖&#xff0c;更何况还是长达数月&#xff01; 在CP Markets申请出金四个多…

LINE社群:为您的跨境出海业务带来更多流量

LINE 社群就是一个大型的公开聊天室&#xff0c;通过LINE社群不需要将对方添加为好友就可以聊天。它主要是以「兴趣」作为区分&#xff0c;所以商家可以在社群中找到不少潜在客户。尤其是面向台湾、日本、泰国这些地区的商家&#xff0c;LINE在这些地区的普及度很高&#xff0c…

10000的单子谈崩了,坚持用beego什么骚操作?

今天有个客户询盘&#xff0c;想仿制一个旅游的网站&#xff0c;一句话差点让我当场拒绝&#xff1a;前端都是静态的&#xff0c;网上有很多工具可以下载源代码&#xff0c;后端接入支付&#xff0c;做个简单的统计&#xff0c;客服&#xff0c;再接入google地图就行了...... 简…

【JAVA重要知识 | 第六篇】Java集合类使用总结(List、Set、Map接口及常见实现类)以及常见面试题

文章目录 6.Java集合类使用总结6.1概览6.1.1集合接口类特性6.1.2List接口和Set接口的区别6.1.3简要介绍&#xff08;1&#xff09;List接口&#xff08;2&#xff09;Set接口&#xff08;3&#xff09;Map接口 6.2Collection接口6.3List接口6.3.1ArrayList6.3.2LinkedList—不常…

PyCharm无代码提示解决

PyCharm无代码提示解决方法 在使用PyCharm工具时&#xff0c;调用方法却无法进行提示&#xff0c;针对PyCharm无代码提示整理下解决方案 1、Python内置语法无智能提示 复现&#xff1a;我这里以urllib库读取网页内容为例&#xff0c;在通过urlopen(&#xff09;之后调用getur…

Python打包为可执行文件

一文带你搞定python脚本(.py)打包为可执行文件(.exe) 文章目录 一文带你搞定python脚本(.py)打包为可执行文件(.exe)01、为什么要打包Python脚本&#xff1f;02、打包步骤&#xff1f;第一步&#xff1a;环境配置与操作包安装第二步&#xff1a;开始打包第三步&#xff1a;输入…

汽车行业一项网络安全标准实践指南发布,SSL证书助力传输通道加密,确保数据安全

2024年3月7日&#xff0c;全国网络安全标准化技术委员会秘书处发布了《网络安全标准实践指南——车外画面局部轮廓化处理效果验证》&#xff08;以下简称《实践指南》&#xff09;&#xff0c;旨在指导汽车数据处理者对车外画面进行人脸、车牌局部轮廓化处理效果的自行验证。《…

图的链式前向星存储与搜索

图的存储与搜索 链式前向星存储 图的存储方式有很多种&#xff0c;但是也都有各自的优缺点。例如&#xff1a;采用邻接矩阵的形式存储的时候&#xff0c;存储比较简单&#xff0c;但是遍历或者处理的时候就会比较浪费时间&#xff1b;而采用邻接表存储&#xff0c;则效率会有…
最新文章