国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

數據實時更新的多種實現方式,你會嗎?

開發 前端
Web 應用愈發復雜,用戶對實時交互體驗的要求也越來越高,比如:社媒的即時通訊、大屏的數據更新、實時消息的提醒等,這些都表明實時交互已成高品質應用的必備特性。

一、前言

如今,Web 應用愈發復雜,用戶對實時交互體驗的要求也越來越高,比如:社媒的即時通訊、大屏的數據更新、實時消息的提醒等,這些都表明實時交互已成高品質應用的必備特性。而作為開發者,我們常面對復雜的開發環境,要應對即時通訊與數據實時更新的問題。那么,該如何精準高效實現這些功能呢?我們將共同探討下,輪詢、Web Socket 、SSE(Server-Sent Events) 三種解決方案,最終根據當下場景選出最優方案,打造更為出色的產品。

二、方案一:輪詢(Polling)

1. 短輪詢

實現短輪詢,我們可以采用定時器的方式來實現,讓客戶端每隔較短固定時間就向服務端發起請求,無論服務器有無新消息,都會正常給予回應。短輪詢的優劣勢一目了然。優勢在于,容易理解、實現過程簡便,同時兼容性又很好,在幾乎所有支持 HTTP 協議的瀏覽器及服務器環境都能很好的運行短輪詢。不過,缺點也非常顯而易見。當按照很短的固定時間間隔去頻繁請求數據,如果此時的數據并未更新,這些請求就成了無效請求,但是每一個無效的請求都得完成 HTTP 建立連接的一系列流程,像三次握手 、 四次揮手 ,這無疑造成了不必要的資源浪費。同時也是由于按固定間隔請求,數據更新也可能會存在延遲的現象,在要求實時性的場景下就不滿足了。

圖片圖片

2. 長輪詢

相對于短輪詢,長輪詢的實現過程會復雜一些。首先,同樣是由客戶端向服務端發送HTTP請求后,不過與短輪詢的差別在于,服務器接到請求后并不即刻返回響應,而是選擇將該請求暫時掛起,靜靜等待數據更新,或是直至達到特定的超時時間(這個超時時間通常比短輪詢間隔長)。在等待期間,如果有數據更新了,就會立即將新數據返回給客戶端,若一直未等到數據更新,直到達到超時時間,服務器才返回一個空響應或者告知客戶端無新數據。客戶端收到響應后,無論是否有新數據,都會立即再次發起新的長輪詢請求,如此循環往復。

這種長輪詢方式相較短輪詢存在一定優勢,首先減少了無效請求的次數,因為只有在數據更新的時候,服務器才會響應,實時性得到了增強,也同時在一定程度上節省了網絡資源。長輪詢雖然減少了無效請求,但是長時間掛起的請求仍會占用服務器的內存、線程等關鍵資源。若同時存在大量長輪詢請求,且長時間處于等待數據更新狀態,服務器資源可能會被大量消耗,同樣可能引發性能問題。

圖片圖片

由此可見, 無論是運用長輪詢還是短輪詢策略,在對實時性有著嚴格要求的場景之下這都不是一個非常好的方案。一方面,頻繁的無效請求以及長時間掛起的連接,極易造成服務器資源的浪費。另一方面,由于輪詢時間間隔的固定性,一旦設置的不合理,就可能錯失數據更新的最佳時機,無法及時將關鍵信息推送給客戶端,導致實時交互出現延遲。

三、方案二:Web Socket

Web Socket 是一種基于單個 TCP 連接的協議,擁有實現 全雙工 通信的能力。它讓客戶端和服務端可以雙向、實時傳輸數據,擺脫了傳統 HTTP 請求那種請求 - 響應模式的限制。有了 Web Socket,服務器能隨時主動給客戶端推送消息,客戶端也能馬上向服務器發數據,就如同構建起了一條實時雙向通道。

圖片圖片

1.Web Socket通信原理

1)握手階段

  • 初始請求階段

a.首先,我們可以從下圖實現效果中看出來,起始于客戶端向服務端發送了一個HTTP請求,但這個請求和常規的HTTP請求又不太一致,他包含了兩個特殊的請求頭, Upgrade: websocket  和  Connection: Upgrade。

b.Upgrade: websocket 像是一個信號,它的作用就是用來告知服務器,客戶端希望將當前的通信協議從 HTTP升級為Web Socket協議。

c.Connection: Upgrade 是與Upgrade: websocket 進行配合使用的,它的作用是告訴服務器,不要把這個請求當作普通的 HTTP 請求來處理,而是要關注 “Upgrade” 請求頭中的內容,按照要求進行協議的升級。

  • 服務器響應階段
  • 服務器收到客戶端的升級請求后,如果支持 Web Socket 協議,就會返回一個響應來完成握手過程。響應狀態碼通常是 101,表示 協議切換。響應頭也會包含和客戶端請求對應的 Upgrade 和 Connection 字段,確認連接升級。Sec - WebSocket - Accept ,它是根據客戶端請求中的 Sec - WebSocket - Key 生成的,用于安全驗證。通過這個握手過程,雙方就建立了一個穩定的 Web Socket 連接這樣,這個連接是基于 TCP的,為后續的雙向通信做好了準備。

2) 數據傳輸階段

  • 我們從下圖中可以看出,Web socket全雙工通道的特點,客戶端可以向服務端主動發送消息,服務端也可以推送數據到服務端。具體的數據格式,我們可以通過抓包軟件來進行抓包看下。

3) 連接維護和關閉階段

  • 在整個通信過程中,Web Socket 協議要求客戶端和服務器都要維護連接的狀態。連接狀態包括連接是否打開、正在關閉或者已經關閉等。客戶端和服務器通過心跳機制(發送周期性的小數據包來檢測對方是否還在線)或者其他自定義的連接檢測方法來確保連接的穩定性。
  • 當需要關閉 WebSocket 連接時,無論是客戶端還是服務器都可以發起關閉請求。關閉請求也是通過發送一個特定的幀(關閉幀)來實現的。對方在收到關閉幀后,會進行一些必要的清理工作,如釋放資源等,然后關閉連接。

2.示例

  • 模擬客戶端代碼
<div id="app">
  <input v-model="message" placeholder="輸入要發送的消息" />
  <button @click="sendMessage">發送消息</button>
  <div>
    <h3>收到的回復記錄:</h3>
    <ul>
      <li v-for="(msg, index) in receivedMessages" :key="msg">{{ msg }}</li>
    </ul>
  </div>
</div>

<script>
  const app = new Vue({
    el: "#app",
    data() {
      return {
        message: "",
        receivedMessages: [], // 新增數組用于存儲所有收到的消息
        socket: null,
      };
    },
    mounted() {
      // 創建WebSocket連接,這里的地址要和后端服務器監聽的地址對應,這里假設后端在本地3000端口
      this.socket = new WebSocket("ws://localhost:3000");
      // 連接成功時觸發的事件
      this.socket.addEventListener("open", () => {
        console.log("已連接到WebSocket服務器");
      });
      // 接收服務器發送消息的事件
      this.socket.addEventListener("message", (event) => {
        const receivedMsg = event.data;
        this.receivedMessages.push(receivedMsg); // 將收到的消息添加到數組中
      });
      // 連接關閉時觸發的事件
      this.socket.addEventListener("close", () => {
        console.log("與WebSocket服務器的連接已關閉");
      });
    },
    methods: {
      sendMessage() {
        if (this.socket.readyState === WebSocket.OPEN) {
          this.socket.send(this.message);
          this.message = "";
        } else {
          console.log("WebSocket連接未就緒,無法發送消息");
        }
      },
    },
  });
</script>
  • 模擬服務端發送請求

注意:下方代碼中,定時器僅用來模擬,在實際業務中應該替換為業務代碼

const WebSocket = require('ws');

// 創建WebSocket服務器實例,監聽在3000端口,你可以根據需求修改端口號
const wss = new WebSocket.Server({ port: 3000 });

// 用于存儲已連接的客戶端WebSocket實例,方便后續向所有客戶端發送消息等操作
const clients = [];

// 當有客戶端連接時觸發的事件
wss.on('connection', (ws) => {
  console.log('客戶端已連接');
  clients.push(ws);

  // 接收客戶端發送的消息
  ws.on('message', (message) => {
    console.log(`收到客戶端消息: ${message}`);
    // 這里簡單地將收到的消息加上一個后綴后再發回客戶端
    const responseMessage = `你發送的消息是:${message}`;
    ws.send(responseMessage);
  });

  // 當客戶端關閉連接時觸發的事件
  ws.on('close', () => {
    console.log('客戶端已斷開連接');
    const index = clients.indexOf(ws);
    if (index > -1) {
      clients.splice(index, 1);
    }
  });
});

// 【注意: 模擬一個定時任務,每隔1秒向所有已連接的客戶端發送一條消息,你可以編寫自己的業務代碼】
setInterval(() => {
  const messageToSend = '這是服務端主動發送的消息,當前時間:' + new Date().toLocaleString();
  clients.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(messageToSend);
    }
  });
}, 1000);

console.log('WebSocket服務器已啟動,正在監聽3000端口...');
  • 實現效果

圖片圖片

圖片圖片

3. 特點

相較于傳統的 HTTP 請求,Web Socket 在實時性方面展現出了卓越優勢,它打破了以往被動等待響應的模式,服務器得以實時且主動地將數據推送至客戶端。在面對高實時性的場景下,大大的提升了用戶體驗。并且只需建立一次 TCP 連接,后續數據傳輸高效便捷,既減少了網絡帶寬的無謂占用,又減輕了服務器頻繁處理連接請求的負擔。然而,當應用場景出現變化,假設客戶端僅僅是獲取服務端推送的消息,自身并無向服務端發送信息的需求,此時,我們可以考慮下 SSE(Server-Sent Events)這個方案。

四、方案三:SSE

SSE(Server-Sent Events) 同樣具備了服務端主動向客戶端推送數據的能力,而無需客戶端不斷地發起請求。與Web Socket不同的是,SSE 是基于 HTTP 協議的,使用的是單向通信, 而Web Socket是基于TCP協議的,使用的話雙向通信。

圖片圖片

1、SSE通信原理

1) 客戶端發起請求

  • 客戶端需要發送一個特定的請求告知服務器準備接收事件。在傳統的 HTTP 請求 - 響應模式中,一次請求完成后連接通常會關閉,但 SSE 通過在服務器端和客戶端設置特定的頭部信息,讓連接持續開啟。例如:設置了Content - Type頭部為text/event - stream,并設置Cache - Control為no - cache以及Connection為keep - alive,這樣告知客戶端,這是一個 SSE 連接,數據會持續推送,并且不需要緩存數據。客戶端只需向服務器發送一個普通的 HTTP 請求,指向服務器端提供 SSE 服務的特定端點就行,例如/events,就可以順利開啟SSE連接。

2)服務器響應請求

  • 服務器收到客戶端請求后,會維持一個長連接,并且定期向客戶端發送事件數據。每個事件都是通過特定的格式(例如 data:\n\n)發送給客戶端的。

3) 客戶端接收數據

  • 客戶端通過 JavaScript 的 EventSource 對象接收從服務器推送過來的數據。這些數據可以是普通文本,也可以是 JSON 格式的對象,取決于服務器如何發送。

4) 事件流的關閉

  • 一旦不再需要推送數據,比如客戶端主動關閉連接,又或是中途出現錯誤,導致無法繼續推送時,服務器便會果斷關閉連接。

2、示例

  • 服務端,使用express框架為例

注意:下方代碼中,定時器僅用來模擬,在實際業務中應該替換為業務代碼

const express = require('express');
const app = express();
const port = 3000;

// 設置響應頭,表明這是一個SSE流
app.get('/events', (req, res) => {
    res.setHeader('Content-Type','text/event-stream');
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');

    // 【注意:模擬定時發送數據(實際應用中需要根據真實業務邏輯觸發發送)!!!】
    const interval = setInterval(() => {
        const data = `data: { "time": "${new Date().toLocaleString()}"}\n\n`;
        res.write(data);
    }, 3000);

    // 當客戶端關閉連接時,清除定時器
    req.on('close', () => {
        clearInterval(interval);
    });
});

app.listen(port, () => {
    console.log(`服務器運行在 http://localhost:${port}`);
});
  • 模擬客戶端代碼
mounted() {
  const source = new EventSource('http://localhost:3000/events');
  source.onmessage = (event) => {
      const data = JSON.parse(event.data); // data 就是發送的消息
      this.message = data.message;
  };
  source.onerror = (error) => {
      console.log('SSE連接出錯:', error);
  };
}
  • 實現效果

圖片圖片

圖片圖片

3.特點

對于SSE來說,優勢上在于簡單易用,客戶端用 EventSource可以接收,服務器端定期發數據即可推送。且單向通信、基于長連接,服務器資源消耗低。不過,SSE 是有局限的。只能夠進行單向通信,現代瀏覽器大多支持,但是IE或者舊版本瀏覽器不支持。SSE 只支持文本格式的數據流,不支持二進制數據傳輸。總之,SSE 在合適場景能發揮優勢,支撐實時數據推送需求。

五、總結

上述文章中,介紹了輪詢、Web Socket、SSE 三種方案。適合的場景也有一些差別,例如:輪詢的方式可以在更新頻率不高的場景下使用、Web Socket可以在需要雙向交互的場景下使用、SSE適用于服務器到客戶端的單向數據流的場景下使用。開發者可以根據場景選擇最優方案,提升產品實時交互體驗。

責任編輯:武曉燕 來源: 大轉轉FE
相關推薦

2016-05-03 14:02:44

2024-07-03 08:02:19

MySQL數據搜索

2021-08-19 15:36:09

數據備份存儲備份策略

2025-01-10 09:15:57

2014-01-22 11:22:44

華為HANA一體機FusionCube大數據分析

2024-02-22 08:31:26

數據恢復工具MySQL回滾SQL

2021-09-13 07:23:52

Go Set 設計

2011-06-22 10:37:08

rsyncinotify

2021-02-26 05:21:56

MySQL數據設計

2018-04-03 16:24:34

分布式方式

2017-01-16 14:13:37

分布式數據庫

2023-01-31 08:34:19

2022-07-05 08:05:00

策略模式接口實現類

2020-09-28 14:24:09

字典Dictionary遍歷

2019-05-07 15:49:27

AI人工智能藝術

2024-10-18 08:00:00

SpringBoot框架開發

2010-07-13 10:40:30

唐駿

2024-09-02 09:31:19

2020-06-01 15:13:41

騰訊云圖數據庫

2019-07-05 11:01:59

Google電子商務搜索引擎
點贊
收藏

51CTO技術棧公眾號

国产主播自拍av| 亚洲综合一区二区| 久久久视频在线| 99久久婷婷国产综合精品首页| 九色porny自拍视频在线播放 | 国内精品卡一卡二卡三新区| 国产69精品久久久久9999人| 在线视频观看一区| 免费观看又污又黄在线观看国产| 国产a久久麻豆| 日本免费在线视频不卡一不卡二| 国产精品一区二区a| 激情都市一区二区| 超级碰碰视频| 欧美精品日韩一区| 欧洲精品99毛片免费高清观看| 欧美中文在线字幕| 麻豆精品国产传媒mv男同| 性chinese极品按摩| 亚洲精品第1页| 成人福利网址| 免费观看日韩电影| 日本视频一区二区在线观看| 国产探花一区二区| 色偷偷91综合久久噜噜| www视频在线观看| 欧美日韩一本到| 国产视频福利在线| 一区二区三区四区不卡在线| 国产精品高清免费在线观看| 四虎影院观看视频在线观看 | 亚洲片在线资源| 大胆人体一区| 欧美区在线观看| 免费观看日韩毛片| 你懂的网址国产 欧美| 亚洲丁香久久久| 黄色片在线看| 欧美日韩一区二区不卡| 91视频成人免费| av日韩亚洲| 玖玖在线精品| 91亚洲精品一区二区| 国产亚洲一区二区三区啪| 成人a免费视频| 日韩国产精品久久久| 成年人看的毛片| 亚洲毛片在线免费| 久久精品国产久精国产| av在线资源站| 高清一区二区三区视频| 亚洲成av人影院| 久久亚洲道色| 我要看一级黄色大片| 日韩视频免费观看高清完整版| 成人免费电影网址| 久草在.com| 欧美精品一区男女天堂| 成人在线视频国产| 91文字幕巨乱亚洲香蕉| 国产乱子伦一区二区三区国色天香| 国产一区二区三区四区五区在线 | 成人在线电影网| 久久精品二区三区| 久久全国免费视频| 亚洲精品国产偷自在线观看| 国产日韩在线免费| 99热这里只有精品8| 黄色三级中文字幕| 亚洲人成网站在线| 国产在线一二三区| 亚洲成av人乱码色午夜| 日本一区二区三区电影免费观看| 国产精品入口尤物| 婷婷六月综合网| 亚亚洲欧洲精品| 欧美国产精品一区| 电影天堂久久| 这里只有精品电影| 亚洲精品一区二| 女一区二区三区| 国产精品天天摸av网| 日韩中文字幕精品| 免费成人美女女| 久久婷婷国产综合精品青草| 波多野结衣在线| 午夜国产精品一区| 国产毛片毛片| 久久看人人爽人人| 国产在线播放观看| 激情综合网激情| 色老板在线观看| 亚洲精品少妇网址| 99re视频精品| 大地资源第二页在线观看高清版| 一区二区国产在线观看| 欧美亚洲视频一区二区| 极品束缚调教一区二区网站| 欧美精品videossex性护士| 19禁羞羞电影院在线观看| 亚洲激情六月丁香| 超级碰在线观看| 久久久精品网| 午夜精品久久久久久久男人的天堂| 二区在线观看| 色偷偷88欧美精品久久久| 黄页网站在线| 91精品久久久久久久久久| 五月激情综合网| 正在播放日韩欧美一页| 性欧美视频videos6一9| 亚洲h色精品| 美女精品视频在线| 色偷偷色偷偷色偷偷在线视频| jlzzjlzz欧美大全| 国产女人18毛片| 一区中文字幕在线观看| 久久久一本精品99久久精品| 成人h视频在线| 国产精品成人久久久久| 97精品久久久中文字幕免费| 亚洲电影天堂av| 在线精品视频一区二区三四| 不卡一区在线观看| 久久久久美女| 自拍偷拍欧美日韩| 欧美xxxx免费虐| 成人性生交大片免费看午夜| 日韩精品一区二区在线视频| 成人精品视频99在线观看免费 | 久久涩涩网站| 91福利国产成人精品照片| 日本亚洲欧美天堂免费| 卡通欧美亚洲| 国精一区二区三区| 啦啦啦中文在线观看日本| 国产玉足脚交久久欧美| 亚洲一区二区三区777| 国产日韩精品在线观看| 欧美裸体男粗大视频在线观看| 久久精品国产96久久久香蕉| 电影一区二区| 亚洲成人在线网| 夜夜嗨av一区二区三区| 国产欧美日韩在线一区二区| 又黄又爽毛片免费观看| 欧美激情国产精品| 在线免费观看不卡av| 久久香蕉精品| 成人羞羞动漫| 国产一区日韩| 亚洲国产片色| 蜜桃视频在线观看一区二区| 久久亚洲图片| 国产呦精品一区二区三区网站| 国产一区二区三区综合| 久久婷婷一区二区三区| 亚洲一区二区三区四区不卡| 在线亚洲一区观看| 亚洲成人久久一区| 久久在线精品视频| 99国精产品一二二线| 男人的天堂avav| 免费日韩中文字幕| 91短视频在线| 日本成人三级电影| 国产精品久久观看| 国产精品日本一区二区不卡视频 | 极品尤物一区| 蜜桃视频在线观看播放| 爱情岛亚洲播放路线| h片在线播放| 免费av在线电影| 亚洲欧洲成人| 9999热视频在线观看| 美女网站视频一区| 国产日产一区二区三区| 欧美18xxxxx| 国产中文字幕第一页| 全网国产福利在线播放| 男女羞羞视频在线观看| 西野翔中文久久精品字幕| 日韩电影免费在线| 久久久国产精品一区| 狠狠噜天天噜日日噜| 白天操夜夜操| 调教在线观看| 激情小说 在线视频| 国产美女性感在线观看懂色av| 性欧美videoshd高清| 色是在线视频| 免费a级人成a大片在线观看| 亚洲第一会所| 一本不卡影院| 久久久精品五月天| 日韩成人av影视| 福利一区二区在线| 樱花草国产18久久久久| 日本乱人伦一区| 精品成人a区在线观看|