<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          你還在使用 WebSocket 實(shí)現(xiàn)實(shí)時(shí)消息推送嗎?

          共 9974字,需瀏覽 20分鐘

           ·

          2024-05-21 10:30

          來(lái)源:juejin.cn/post/7325730345840066612

          ?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對(duì)一提問(wèn) / 學(xué)習(xí)打卡 /  每月贈(zèng)書(shū)


          新項(xiàng)目:仿小紅書(shū)(微服務(wù)架構(gòu))正在更新中... , 全棧前后端分離博客項(xiàng)目 2.0 版本完結(jié)啦, 演示鏈接http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開(kāi)發(fā),從 0 到 1 講解每個(gè)功能點(diǎn)開(kāi)發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了261小節(jié),累計(jì)41w+字,講解圖:1806張,還在持續(xù)爆肝中.. 后續(xù)還會(huì)上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有1400+小伙伴加入(早鳥(niǎo)價(jià)超低)


          • 服務(wù)端向客戶端推送數(shù)據(jù)的實(shí)現(xiàn)方案有哪幾種?
            • 輪詢簡(jiǎn)介
            • websocket簡(jiǎn)介
            • SSE簡(jiǎn)介
          • websocket和SSE有什么區(qū)別?
            • 輪詢
            • Websocket和SSE
            • Websocket和SSE分別適用于什么業(yè)務(wù)場(chǎng)景?
          • SSE有哪些主要的API?
            • SSE連接狀態(tài)
            • SSE相關(guān)事件
            • 數(shù)據(jù)格式
          • 如何實(shí)操一個(gè)SSE鏈接?Demo↓
            • 前端代碼Demo
            • 后端代碼Demo(node的express)
          • 總結(jié)

          在日常的開(kāi)發(fā)中,我們經(jīng)常能碰見(jiàn)服務(wù)端需要主動(dòng)推送給客戶端數(shù)據(jù)的業(yè)務(wù)場(chǎng)景,比如數(shù)據(jù)大屏的實(shí)時(shí)數(shù)據(jù),比如消息中心的未讀消息,比如聊天功能等等。

          本文主要介紹SSE的使用場(chǎng)景和如何使用SSE。

          圖片

          服務(wù)端向客戶端推送數(shù)據(jù)的實(shí)現(xiàn)方案有哪幾種?

          我們常規(guī)實(shí)現(xiàn)這些需求的方案有以下三種

          • 輪詢
          • websocket
          • SSE

          輪詢簡(jiǎn)介

          在很久很久以前,前端一般使用輪詢來(lái)進(jìn)行服務(wù)端向客戶端進(jìn)行消息的偽推送,為什么說(shuō)輪詢是偽推送?因?yàn)檩喸儽举|(zhì)上還是通過(guò)客戶端向服務(wù)端發(fā)起一個(gè)單項(xiàng)傳輸?shù)恼?qǐng)求,服務(wù)端對(duì)這個(gè)請(qǐng)求做出響應(yīng)而已。通過(guò)不斷的請(qǐng)求來(lái)實(shí)現(xiàn)服務(wù)端向客戶端推送數(shù)據(jù)的錯(cuò)覺(jué)。并不是服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù)。

          顯然,輪詢一定是上述三個(gè)方法里最下策的決定。

          輪詢的缺點(diǎn):

          • 首先輪詢需要不斷的發(fā)起請(qǐng)求,每一個(gè)請(qǐng)求都需要經(jīng)過(guò)http建立連接的流程(比如三次握手,四次揮手),是沒(méi)有必要的消耗。
          • 客戶端需要從頁(yè)面被打開(kāi)的那一刻開(kāi)始就一直處理請(qǐng)求。雖然每次輪詢的消耗不大,但是一直處理請(qǐng)求對(duì)于客戶端來(lái)說(shuō)一定是不友好的。
          • 瀏覽器請(qǐng)求并發(fā)是有限制的。比如Chrome 最大并發(fā)請(qǐng)求數(shù)目為 6,這個(gè)限制還有一個(gè)前提是針對(duì)同一域名的,超過(guò)這一限制的后續(xù)請(qǐng)求將會(huì)被阻塞。而輪詢意味著會(huì)有一個(gè)請(qǐng)求長(zhǎng)時(shí)間的占用并發(fā)名額。
          • 而如果輪詢時(shí)間較長(zhǎng),可能又沒(méi)有辦法非常及時(shí)的獲取數(shù)據(jù)

          websocket簡(jiǎn)介

          websocket是一個(gè)雙向通訊的協(xié)議,他的優(yōu)點(diǎn)是,可以同時(shí)支持客戶端和服務(wù)端彼此相互進(jìn)行通訊。功能上很強(qiáng)大。

          缺點(diǎn)也很明顯,websocket是一個(gè)新的協(xié)議,ws/wss。也就是說(shuō),支持http協(xié)議的瀏覽器不一定支持ws協(xié)議。

          相較于SSE來(lái)說(shuō),websocket因?yàn)楣δ芨鼜?qiáng)大。結(jié)構(gòu)更復(fù)雜。所以相對(duì)比較重。

          websocket對(duì)于各大瀏覽器的兼容性↓

          圖片

          SSE簡(jiǎn)介

          sse是一個(gè)單向通訊的協(xié)議也是一個(gè)長(zhǎng)鏈接,它只能支持服務(wù)端主動(dòng)向客戶端推送數(shù)據(jù),但是無(wú)法讓客戶端向服務(wù)端推送消息。

          長(zhǎng)鏈接是一種HTTP/1.1的持久連接技術(shù),它允許客戶端和服務(wù)器在一次TCP連接上進(jìn)行多個(gè)HTTP請(qǐng)求和響應(yīng),而不必為每個(gè)請(qǐng)求/響應(yīng)建立和斷開(kāi)一個(gè)新的連接。長(zhǎng)連接有助于減少服務(wù)器的負(fù)載和提高性能。

          SSE的優(yōu)點(diǎn)是,它是一個(gè)輕量級(jí)的協(xié)議,相對(duì)于websockte來(lái)說(shuō),他的復(fù)雜度就沒(méi)有那么高,相對(duì)于客戶端的消耗也比較少。而且SSE使用的是http協(xié)議(websocket使用的是ws協(xié)議),也就是現(xiàn)有的服務(wù)端都支持SSE,無(wú)需像websocket一樣需要服務(wù)端提供額外的支持。

          注意:IE大魔王不支持SSE

          SSE對(duì)于各大瀏覽器的兼容性↓

          圖片

          注意哦,上圖是SSE對(duì)于瀏覽器的兼容不是對(duì)于服務(wù)端的兼容。

          websocket和SSE有什么區(qū)別?

          輪詢

          對(duì)于當(dāng)前計(jì)算機(jī)的發(fā)展來(lái)說(shuō),幾乎很少出現(xiàn)同時(shí)不支持websocket和sse的情況,所以輪詢是在極端情況下瀏覽器實(shí)在是不支持websocket和see的下策。

          Websocket和SSE

          我們一般的服務(wù)端和客戶端的通訊基本上使用這兩個(gè)方案。首先聲明:這兩個(gè)方案沒(méi)有絕對(duì)的好壞,只有在不同的業(yè)務(wù)場(chǎng)景下更好的選擇。

          SSE的官方對(duì)于SSE和Websocket的評(píng)價(jià)是

          • WebSocket是全雙工通道,可以雙向通信,功能更強(qiáng);SSE是單向通道,只能服務(wù)器向?yàn)g覽器端發(fā)送。
          • WebSocket是一個(gè)新的協(xié)議,需要服務(wù)器端支持;SSE則是部署在HTTP協(xié)議之上的,現(xiàn)有的服務(wù)器軟件都支持。
          • SSE是一個(gè)輕量級(jí)協(xié)議,相對(duì)簡(jiǎn)單;WebSocket是一種較重的協(xié)議,相對(duì)復(fù)雜。
          • SSE默認(rèn)支持?jǐn)嗑€重連,WebSocket則需要額外部署。
          • SSE支持自定義發(fā)送的數(shù)據(jù)類型。

          Websocket和SSE分別適用于什么業(yè)務(wù)場(chǎng)景?

          對(duì)于SSE來(lái)說(shuō),它的優(yōu)點(diǎn)就是輕,而且對(duì)于服務(wù)端的支持度要更好。換言之,可以使用SSE完成的功能需求,沒(méi)有必要使用更重更復(fù)雜的websocket。

          比如:數(shù)據(jù)大屏的實(shí)時(shí)數(shù)據(jù),消息中心的消息推送等一系列只需要服務(wù)端單方面推送而不需要客戶端同時(shí)進(jìn)行反饋的需求,SSE就是不二之選。

          對(duì)于Websocket來(lái)說(shuō),他的優(yōu)點(diǎn)就是可以同時(shí)支持客戶端和服務(wù)端的雙向通訊。所適用的業(yè)務(wù)場(chǎng)景:最典型的就是聊天功能。這種服務(wù)端需要主動(dòng)向客戶端推送信息,并且客戶端也有向服務(wù)端推送消息的需求時(shí),Websocket就是更好的選擇。

          SSE有哪些主要的API?

          建立一個(gè)SSE鏈接 :var source = new EventSource(url);

          SSE連接狀態(tài)

          source.readyState
          • 0,相當(dāng)于常量EventSource.CONNECTING,表示連接還未建立,或者連接斷線。
          • 1,相當(dāng)于常量EventSource.OPEN,表示連接已經(jīng)建立,可以接受數(shù)據(jù)。
          • 2,相當(dāng)于常量EventSource.CLOSED,表示連接已斷,且不會(huì)重連。

          SSE相關(guān)事件

          • open事件(連接一旦建立,就會(huì)觸發(fā)open事件,可以定義相應(yīng)的回調(diào)函數(shù))
          • message事件(收到數(shù)據(jù)就會(huì)觸發(fā)message事件)
          • error事件(如果發(fā)生通信錯(cuò)誤(比如連接中斷),就會(huì)觸發(fā)error事件)

          數(shù)據(jù)格式

          Content-Type: text/event-stream //文本返回格式
          Cache-Control: no-cache  //不要緩存
          Connection: keep-alive //長(zhǎng)鏈接標(biāo)識(shí)

          SSE相關(guān)文檔:

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

          顯然,如果直接看api介紹不論是看這里還是看官網(wǎng),大部分同學(xué)都是比較懵圈的狀態(tài),那么我們寫(xiě)個(gè)demo來(lái)看一下?

          我更建議您先把Demo跑起來(lái),然后在看看上面這個(gè)w3cschool的SSE文檔。兩個(gè)配合一起看,會(huì)更方便理解些。

          如何實(shí)操一個(gè)SSE鏈接?Demo↓

          這里Demo前端使用的就是最基本的html靜態(tài)頁(yè)面連接,沒(méi)有使用任何框架。

          后端選用語(yǔ)言是node,框架是Express。

          理論上,把這兩段端代碼復(fù)制過(guò)去跑起來(lái)就直接可以用了。

          • 第一步,建立一個(gè)index.html文件,然后復(fù)制前端代碼Demo到index.html文件中,打開(kāi)文件
          • 第二步,進(jìn)入一個(gè)新的文件夾,建立一個(gè)index.js文件,然后將后端Demo代碼復(fù)制進(jìn)去,然后在該文件夾下執(zhí)行
          npm init          //初始化npm       
          npm i express     //下載node express框架
          node index        //啟動(dòng)服務(wù)

          圖片

          在這一層文件夾下執(zhí)行命令。

          完成以上操作就可以把項(xiàng)目跑起來(lái)了

          前端代碼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;
          }
              
          //判斷當(dāng)前瀏覽器是否支持SSE
            let source = ''
           if (!!window.EventSource) {
              source = new EventSource('http://localhost:8088/sse/');
           }else{
              throw new Error("當(dāng)前瀏覽器不支持SSE")
           }

           //對(duì)于建立鏈接的監(jiān)聽(tīng)
           source.onopen = function(event) {
             console.log(source.readyState);
             console.log("長(zhǎng)連接打開(kāi)");
           };

           //對(duì)服務(wù)端消息的監(jiān)聽(tīng)
           source.onmessage = function(event) {
             console.log(JSON.parse(event.data));
             console.log("收到長(zhǎng)連接信息");
             let li = createLi(JSON.parse(event.data));
             document.getElementById("ul").appendChild(li)
           };

           //對(duì)斷開(kāi)鏈接的監(jiān)聽(tīng)
           source.onerror = function(event) {
             console.log(source.readyState);
             console.log("長(zhǎng)連接中斷");
           };

          </script>
          </html>

          后端代碼Demo(node的express)

          const express = require('express'); //引用框架
          const app = express(); //創(chuàng)建服務(wù)
          const port = 8088; //項(xiàng)目啟動(dòng)端口

          //設(shè)置跨域訪問(wèn)
          app.all("*"function(req, res, next) {
           //設(shè)置允許跨域的域名,*代表允許任意域名跨域
           res.header("Access-Control-Allow-Origin"'*');
           //允許的header類型
           res.header("Access-Control-Allow-Headers""Content-Type, Authorization, X-Requested-With");
           //跨域允許的請(qǐng)求方式 
           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', //設(shè)定數(shù)據(jù)類型
                  'Cache-Control''no-cache',// 長(zhǎng)鏈接拒絕緩存
                  'Connection''keep-alive' //設(shè)置長(zhǎng)鏈接
                });

                console.log("進(jìn)入到長(zhǎng)連接了")
                //持續(xù)返回?cái)?shù)據(jù)
                setInterval(() => {
                  console.log("正在持續(xù)返回?cái)?shù)據(jù)中ing")
                  const data = {
                    message: `Current time is ${new Date().toLocaleTimeString()}`
                  };
                  res.write(`data: ${JSON.stringify(data)}\n\n`);
                }, 1000);  
          })

          //創(chuàng)建項(xiàng)目
          app.listen(port, () => {
           console.log(`項(xiàng)目啟動(dòng)成功-http://localhost:${port}`)
          })

          總結(jié)

          • SSE比websocket更輕
          • SSE是基于http/https協(xié)議的
          • websocket是一個(gè)新的協(xié)議,ws/wss協(xié)議
          • 如果只需要服務(wù)端向客戶端推送消息,推薦使用SSE
          • 如果需要服務(wù)端和客戶端雙向推送,請(qǐng)選擇websocket
          • 不論是SSE還是websocket,對(duì)于瀏覽器的兼容性都不錯(cuò)
          • 輪詢是下策,很占用客戶端資源,不建議使用。(不過(guò)偷懶的時(shí)候他確實(shí)方便)
          • IE不支持SSE

          對(duì)了,小程序不支持SSE哦

          ?? 歡迎加入小哈的星球 ,你將獲得: 專屬的項(xiàng)目實(shí)戰(zhàn) / Java 學(xué)習(xí)路線 / 一對(duì)一提問(wèn) / 學(xué)習(xí)打卡 /  每月贈(zèng)書(shū)


          新項(xiàng)目:仿小紅書(shū)(微服務(wù)架構(gòu))正在更新中... , 全棧前后端分離博客項(xiàng)目 2.0 版本完結(jié)啦, 演示鏈接http://116.62.199.48/ 。全程手摸手,后端 + 前端全棧開(kāi)發(fā),從 0 到 1 講解每個(gè)功能點(diǎn)開(kāi)發(fā)步驟,1v1 答疑,直到項(xiàng)目上線。目前已更新了261小節(jié),累計(jì)41w+字,講解圖:1806張,還在持續(xù)爆肝中.. 后續(xù)還會(huì)上新更多項(xiàng)目,目標(biāo)是將Java領(lǐng)域典型的項(xiàng)目都整一波,如秒殺系統(tǒng), 在線商城, IM即時(shí)通訊,Spring Cloud Alibaba 等等,戳我加入學(xué)習(xí),已有1400+小伙伴加入(早鳥(niǎo)價(jià)超低)



              
                 

          1. 我的私密學(xué)習(xí)小圈子~

          2. 官方推出了 Spring AI 框架,Java集成 AI 不再是難事!

          3. 一款輕量級(jí)、高性能、功能強(qiáng)大的內(nèi)網(wǎng)穿透代理服務(wù)器

          4. 不好意思,F(xiàn)astjson 真的該換了!

          最近面試BAT,整理一份面試資料Java面試BATJ通關(guān)手冊(cè),覆蓋了Java核心技術(shù)、JVM、Java并發(fā)、SSM、微服務(wù)、數(shù)據(jù)庫(kù)、數(shù)據(jù)結(jié)構(gòu)等等。

          獲取方式:點(diǎn)“在看”,關(guān)注公眾號(hào)并回復(fù) Java 領(lǐng)取,更多內(nèi)容陸續(xù)奉上。

          PS:因公眾號(hào)平臺(tái)更改了推送規(guī)則,如果不想錯(cuò)過(guò)內(nèi)容,記得讀完點(diǎn)一下在看,加個(gè)星標(biāo),這樣每次新文章推送才會(huì)第一時(shí)間出現(xiàn)在你的訂閱列表里。

          點(diǎn)“在看”支持小哈呀,謝謝啦

          瀏覽 1121
          4點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          4點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  做受 视频毛片下载 | 青娱乐国产无码 | 青青伊人国产 | 精品中文字幕97A片免费视频 | 午夜无码久久 |