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

打印 上一主题 下一主题

主题 1514|帖子 1514|积分 4542

作者:工边页字
链接:https://juejin.cn/post/7325730345840066612
媒介

在一样平常的开辟中,我们经常能遇见服务端需要主动推送给客户端数据的业务场景,比如数据大屏的及时数据,比如消息中央的未读消息,比如聊天功能等等。
本文主要介绍SSE的使用场景和怎样使用SSE。
服务端向客户端推送数据的实现方案有哪几种?

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

  • 轮询
  • websocket
  • SSE
轮询简介

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

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

websocket是一个双向通讯的协议,他的优点是,可以同时支持客户端和服务端彼此相互进行通讯。功能上很强大。
缺点也很明显,websocket是一个新的协议,ws/wss。也就是说,支持http协议的欣赏器不一定支持ws协议。
相较于SSE来说,websocket由于功能更强大。结构更复杂。以是相对比力
websocket对于各大欣赏器的兼容性↓

SSE简介

sse是一个单向通讯的协议也是一个长链接,它只能支持服务端主动向客户端推送数据,但是无法让客户端向服务端推送消息。
  1. 长链接是一种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的评价是

  • WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向欣赏器端发送。
  • WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有的服务器软件都支持。
  • SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。
  • SSE默认支持断线重连,WebSocket则需要额外部署。
  • SSE支持自界说发送的数据类型。
Websocket和SSE分别适用于什么业务场景?

对于SSE来说,它的优点就是轻,而且对于服务端的支持度要更好。换言之,可以使用SSE完成的功能需求,没有须要使用更重更复杂的websocket。
比如:数据大屏的及时数据,消息中央的消息推送等一系列只需要服务端单方面推送而不需要客户端同时进行反馈的需求,SSE就是不二之选。
对于Websocket来说,他的优点就是可以同时支持客户端和服务端的双向通讯。所适用的业务场景:最典型的就是聊天功能。这种服务端需要主动向客户端推送信息,并且客户端也有向服务端推送消息的需求时,Websocket就是更好的选择。
SSE有哪些主要的API?
  1. 建立一个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事件)
数据格式
  1. Content-Type: text/event-stream //文本返回格式
  2. Cache-Control: no-cache  //不要缓存
  3. Connection: keep-alive //长链接标识
复制代码
显然,如果直接看api介绍岂论是看这里还是看官网,大部分同学都是比力懵圈的状态,*那么我们写个demo来看一下
demo请看下方
我更发起您先把Demo跑起来,然后在看看上SSE文档。两个共同一起看,会更方便理解些。
怎样实操一个SSE链接?Demo↓

这里Demo前端使用的就是最根本的html静态页面连接,没有使用任何框架。 后端选用语言是node,框架是Express。
理论上,把这两段端代码复制过去跑起来就直接可以用了。

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

在这一层文件夹下实行命令。
完成以上操作就可以把项目跑起来了
前端代码Demo
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4.     <meta charset="UTF-8">
  5.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7.     <title>Document</title>
  8. </head>
  9. <body>
  10.     <ul id="ul">
  11.     </ul>
  12. </body>
  13. </html>
复制代码
后端代码Demo(node的express)
  1. const express = require('express'); //引用框架
  2. const app = express(); //创建服务
  3. const port = 8088; //项目启动端口
  4. //设置跨域访问
  5. app.all("*", function(req, res, next) {
  6.         //设置允许跨域的域名,*代表允许任意域名跨域
  7.         res.header("Access-Control-Allow-Origin", '*');
  8.         //允许的header类型
  9.         res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, X-Requested-With");
  10.         //跨域允许的请求方式
  11.         res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
  12.         // 可以带cookies
  13.         res.header("Access-Control-Allow-Credentials", true);
  14.         if (req.method == 'OPTIONS') {
  15.                 res.sendStatus(200);
  16.         } else {
  17.                 next();
  18.         }
  19. })
  20. app.get("/sse",(req,res) => {
  21.     res.set({
  22.         'Content-Type': 'text/event-stream', //设定数据类型
  23.         'Cache-Control': 'no-cache',// 长链接拒绝缓存
  24.         'Connection': 'keep-alive' //设置长链接
  25.       });
  26.       console.log("进入到长连接了")
  27.       //持续返回数据
  28.       setInterval(() => {
  29.         console.log("正在持续返回数据中ing")
  30.         const data = {
  31.           message: `Current time is ${new Date().toLocaleTimeString()}`
  32.         };
  33.         res.write(`data: ${JSON.stringify(data)}\n\n`);
  34.       }, 1000);
  35. })
  36. //创建项目
  37. app.listen(port, () => {
  38.         console.log(`项目启动成功-http://localhost:${port}`)
  39. })
复制代码
效果


总结


  • SSE比websocket更轻
  • SSE是基于http/https协议的
  • websocket是一个新的协议,ws/wss协议
  • 如果只需要服务端向客户端推送消息,保举使用SSE
  • 如果需要服务端和客户端双向推送,请选择websocket
  • 岂论是SSE还是websocket,对于欣赏器的兼容性都不错
  • 轮询是下策,很占用客户端资源,不发起使用。(不过偷懒的时候他确实方便)
  • IE不支持SSE
  • 小白同学demo如果跑不明白可以私信我
对了,小程序不支持SSE哦
更多文章保举:
1.Spring Boot 3.x 教程,太全了!
2.3,000+ 道 Java口试题及答案整理(最新版)
3.免费获取 IDEA 激活码的 7 种方式(最新版)
4.Java & DeepSeek & AI 学习资料分享
5.程序员风雅简历模板分享
觉得不错,别忘了随手点赞+转发哦!

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

八卦阵

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表