「JavaScript深入」Server-Sent Events (SSE):輕量級實時通信技術

Server-Sent Events(SSE)

    • SSE 的特點
      • 1. 單向通信
      • 2. 簡單易用,瀏覽器原生支持
      • 3. 持久連接
      • 4. 純文本傳輸
      • 5. 自動重連機制
      • 6. 輕量級協議
    • SSE 的實現
      • 服務器端實現(Node.js 示例)
        • 1. HTTP 響應頭設置
        • 2. 數據推送模式
        • 3. 服務器端代碼示例
      • 數據格式規范詳解
        • 1. 完整事件結構
        • 2. 錯誤處理示例
      • 客戶端實現(HTML + JavaScript)
        • HTML + JavaScript 代碼示例
        • 高級功能
    • SSE 與 WebSocket 的比較
        • 混合架構實踐
    • SSE 的應用場景
    • 安全與性能優化
        • 1. 安全防護
        • 2. 性能調優
    • SSE擴展方案
        • 1. 斷線續傳實現
        • 2. 二進制數據傳輸
    • 總結

在現代 Web 應用中,實時數據推送成為了關鍵需求之一。例如,在股票行情、天氣更新、社交通知等應用場景中,客戶端需要能夠持續接收服務器端的最新數據。Server-Sent Events (SSE) 是一種基于 HTTP 協議的輕量級實時通信技術,能夠讓服務器主動向客戶端推送消息。

下一節分享了「WebSocket:高效的雙向實時通信技術」


SSE 的特點

1. 單向通信

SSE 是服務器向客戶端推送數據的單向通道。客戶端可以持續接收服務器端的更新,但不會主動向服務器發送數據(除非建立額外的請求)。

2. 簡單易用,瀏覽器原生支持

SSE 使用簡單的文本格式傳輸事件,大多數現代瀏覽器(如 Chrome、Firefox、Edge 和 Safari)都提供了內置支持,無需額外的庫或插件。

3. 持久連接

SSE 采用持久 HTTP 連接(HTTP 長連接),服務器可以連續發送數據流,而無需客戶端重復發送請求。

4. 純文本傳輸

SSE 傳輸的數據是純文本格式,消息之間以換行符 (\n\n) 分隔,便于解析和調試。

5. 自動重連機制

如果 SSE 連接因網絡故障等原因斷開,瀏覽器會自動嘗試重新連接服務器,而無需額外處理。

const es = new EventSource('/sse');
es.onerror = () => { /* 處理中斷 */ };
  • 底層原理: SSE協議規范中定義了客戶端自動重連機制,當連接異常斷開時,瀏覽器默認以指數退避策略(初始約3秒)嘗試重新連接
  • 開發優勢: 相比WebSocket需手動實現斷線重連,SSE顯著降低實時應用開發復雜度
  • 注意事項: 可通過 retry: 字段指定重試間隔(單位:毫秒ms)

6. 輕量級協議

  • 協議開銷: 基于純文本的簡單協議格式,每個消息僅增加約20字節頭部信息
  • 傳輸效率: 適用于高頻小數據量場景(如實時股票報價),避免WebSocket的握手開銷

SSE 的實現

服務器端實現(Node.js 示例)

在服務器端,SSE 通過正確的 HTTP 頭部設置來標識事件流,并以特定格式發送數據。

1. HTTP 響應頭設置
res.writeHead(200, {'Content-Type': 'text/event-stream', // 必須聲明SSE類型'Cache-Control': 'no-cache',         // 禁用瀏覽器緩存'Connection': 'keep-alive',          // 保持長連接'Access-Control-Allow-Origin': '*'   // CORS配置
});
  • 關鍵頭信息:
    • Content-Type 必須為 text/event-stream
    • Cache-Control: no-cache 防止代理服務器緩存
    • X-Accel-Buffering: no(Nginx環境禁用緩沖)
2. 數據推送模式
setInterval(() => {res.write(`data: ${JSON.stringify(data)}\n\n`);
}, 1000);
  • 流式寫入: 必須通過分塊編碼(chunked encoding)持續發送數據
  • 消息邊界: 每條消息必須以 \n\n 結尾,字段間用 \n 分隔
  • 性能優化: 使用寫緩沖區,避免頻繁的TCP包發送
3. 服務器端代碼示例
const http = require('http');http.createServer((req, res) => {res.writeHead(200, {'Content-Type': 'text/event-stream','Cache-Control': 'no-cache','Connection': 'keep-alive'});let clientId = 0;const retryInterval = 5000; // 5秒自動重連const eventSender = setInterval(() => {clientId++;const message = `id: ${clientId}\nevent: update\nretry: ${retryInterval}\ndata: This is message number ${clientId}\n\n`;res.write(message);}, 1000);req.on('close', () => {clearInterval(eventSender);});}).listen(3000, () => {console.log('SSE server running at http://localhost:3000/');
});

數據格式規范詳解

1. 完整事件結構
event: userUpdate\n
data: {"id": 101, "status": "online"}\n
id: 101-20230301\n
retry: 10000\n\n
  • event:自定義事件類型,觸發客戶端對應事件監聽器
  • data:支持多行數據(每行需以 data: 開頭)
    • 建議JSON格式傳輸結構化數據
  • id:事件ID,用于斷線續傳(Last-Event-ID請求頭)
  • retry:控制重連間隔(單位:毫秒)
2. 錯誤處理示例
res.write(`event: error\ndata: 服務端異常\n\n`);
  • 客戶端通過監聽error事件進行異常處理
  • 建議包含錯誤代碼和描述信息的JSON數據

客戶端實現(HTML + JavaScript)

在前端,使用 EventSource API 輕松實現 SSE 連接。

HTML + JavaScript 代碼示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>SSE Demo</title><script>document.addEventListener("DOMContentLoaded", function () {const eventSource = new EventSource('http://localhost:3000/api/notifications');// 自定義事件處理eventSource.addEventListener('update', function(event) {console.log('Received update:', event.data);});// 默認消息類型監聽eventSource.onmessage = function(event) {console.log('General message:', event.data);};// 錯誤處理eventSource.onerror = function(err) {console.error('EventSource failed:', err);};});</script>
</head>
<body><h1>Server-Sent Events Demo</h1><p>Check the console for messages.</p>
</body>
</html>
高級功能
// 自定義請求頭(需CORS支持)
const es = new EventSource('/api/stream', {withCredentials: true 
});// 連接狀態管理
es.onopen = () => console.log('連接已建立');
es.onerror = (e) => {if (e.target.readyState === EventSource.CLOSED) {console.log('連接永久關閉');}
};// 主動關閉連接
document.getElementById('stop').onclick = () => es.close();

SSE 與 WebSocket 的比較

特性SSEWebSocket
協議HTTP長連接獨立的ws/wss協議
壓縮支持支持gzip/brotli壓縮需要擴展實現
消息延遲較高(依賴HTTP層)低延遲(二進制幀)
連接方式服務器推送數據到客戶端客戶端和服務器可雙向通信
適用場景服務器需要頻繁更新數據,如新聞推送、日志更新、實時儀表盤(如監控系統)、新聞/社交媒體Feed流、長輪詢替代方案等需要實時交互,如聊天應用、多人協作、高頻雙向通信(如在線游戲)等
瀏覽器支持原生支持,大多數現代瀏覽器均支持需要 WebSocket API,部分老舊瀏覽器不支持
連接管理自動管理重新連接需手動處理連接丟失與重連
混合架構實踐
// 組合使用案例:SSE推送通知 + WebSocket實現聊天
const notificationStream = new EventSource('/notifications');
const chatSocket = new WebSocket('wss://chat.example.com');// 消息類型路由處理
function handleMessage(data) {if (data.type === 'notification') {// 使用SSE處理} else if (data.type === 'chat') {// 使用WebSocket處理 }
}

SSE 的應用場景

SSE 適用于以下應用場景:

  • 實時新聞推送:新聞網站可使用 SSE 向用戶推送最新的新聞資訊。
  • 股票行情更新:股票交易平臺可以用 SSE 傳輸市場行情數據。
  • 服務器日志實時展示:開發者工具可以通過 SSE 實時顯示服務器日志。
  • 社交通知:社交平臺可利用 SSE 向用戶推送好友動態或點贊通知。

安全與性能優化

1. 安全防護
// 身份驗證示例(Cookie + CORS)
app.use('/secure-stream', (req, res, next) => {if (!validateToken(req.cookies.token)) {return res.status(401).end();}next();
});
  • 認證方案: Cookie驗證、JWT令牌、OAuth2.0
  • 安全頭設置:
    • Content-Security-Policy: default-src 'self'
    • X-Content-Type-Options: nosniff
2. 性能調優
  • 服務端優化:

    • 連接數限制(Nginx worker_connections)
    • 心跳機制保持連接活躍
    setInterval(() => {res.write(':ping\n\n'); // 注釋行作為心跳
    }, 30000);
    
  • 客戶端優化:

    • 合理設置EventSource并發數
    • 及時關閉不需要的連接

SSE擴展方案

1. 斷線續傳實現
// 服務端記錄最后事件ID
let lastId = 0;
app.get('/resumable-stream', (req, res) => {const clientLastId = req.headers['last-event-id'] || 0;// 從clientLastId之后開始發送數據
});
2. 二進制數據傳輸
// 通過Base64編碼傳輸
const buffer = await getImageBuffer();
res.write(`data: ${buffer.toString('base64')}\n\n`);// 客戶端解碼
es.onmessage = (e) => {const img = document.createElement('img');img.src = `data:image/png;base64,${e.data}`;
};

總結

SSE 是一種輕量級的服務器推送技術,適用于服務器單向推送數據的場景。它基于 HTTP,簡單易用,支持持久連接和自動重連,廣泛應用于實時數據更新場景。盡管相比 WebSocket 功能有限,但對于不需要雙向通信的應用,SSE 提供了更簡單、更高效的解決方案。

如果你的應用場景涉及實時數據推送,而不需要客戶端主動發送消息,那么 SSE 可能是一個理想的選擇!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/73883.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/73883.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/73883.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

藍橋杯2023年第十四屆省賽真題-階乘的和

藍橋杯2023年第十四屆省賽真題-階乘的和 時間限制: 2s 內存限制: 320MB 提交: 3519 解決: 697 題目描述 給定 n 個數 Ai&#xff0c;問能滿足 m! 為∑ni1(Ai!) 的因數的最大的 m 是多少。其中 m! 表示 m 的階乘&#xff0c;即 1 2 3 m。 輸入格式 輸入的第一行包含一個整…

影刀RPA拓展-Python變量類型轉換

1. Python變量類型轉換概述 1.1 類型轉換的必要性 Python作為一種動態類型語言&#xff0c;在編程過程中經常需要進行變量類型轉換。這主要是因為不同數據類型在存儲結構、運算規則和使用場景上存在差異&#xff0c;而在實際開發中&#xff0c;我們常常需要對不同類型的數據進…

Python pyqt+flask做一個簡單實用的自動排班系統

這是一個基于Flask和PyQt的排班系統&#xff0c;可以將Web界面嵌入到桌面應用程序中。 系統界面&#xff1a; 功能特點&#xff1a; - 讀取員工信息和現有排班表 - 自動生成排班表 - 美觀的Web界面 - 獨立的桌面應用程序 整體架構&#xff1a; 系統采用前后端分離的架構…

Pycharm接入DeepSeek,提升自動化腳本的寫作效率

一.效果展示&#xff1a; 二.實施步驟&#xff1a; 1.DeepSeek官網創建API key&#xff1a; 創建成功后&#xff0c;會生成一個API key&#xff1a; 2. PyCharm工具&#xff0c;打開文件->設置->插件&#xff0c;搜索“Continue”&#xff0c;點擊安裝 3.安裝完成后&…

Java:Arrays類:操作數組的工具類

文章目錄 Arrays類常見方法SetAll(); 代碼排序如果數組中存儲的是自定義對象 Arrays類 常見方法 SetAll(); 注意&#xff1a; 不能用新的數組接是因為修改的是原數組&#xff0c;所以完了要輸出原數組發現會產生變化參數是數組下標變成灰色是因為還能簡化&#xff08;Lambda…

2025-gazebo配置on vmware,wsl

ros2安裝 # 安裝ros2, 推薦魚香ros一鍵式安裝 wget http://fishros.com/install -O fishros && . fishros安裝版本&#xff1a;ubuntu24.04 ros2 jazzy gazebo Getting Started with Gazebo? — Gazebo ionic documentation ros與gz的版本對應關系&#xff1a; ?…

格力地產更名“珠免集團“ 全面轉型免稅賽道

大灣區經濟網品牌觀察訊&#xff0c;3月18日&#xff0c;格力地產股份有限公司公告宣布&#xff0c;擬將公司名稱變更為"珠海珠免集團股份有限公司"&#xff0c;證券簡稱同步變更為"珠免集團"。此次更名并非簡單的品牌煥新&#xff0c;而是標志著這家曾以房…

網絡編程--服務器雙客戶端聊天

寫一個服務器和客戶端 運行服務器和2個客戶端&#xff0c;實現聊天功能 客戶端1和客戶端2進行聊天&#xff0c;客戶端1將聊天數據發送給服務器&#xff0c;服務器將聊天數據轉發給客戶端2 要求&#xff1a; 服務器使用 select 模型實現 &#xff0c;客戶端1使用 poll 模型實現…

k8s主要控制器簡述(一)ReplicaSet與Deployment

目錄 一、ReplicaSet 關鍵特性 示例 解釋 支持的 Operator 二、Deployment 1. 聲明式更新 示例 2. 滾動更新 示例 3. 回滾 示例 4. ReplicaSet 管理 示例 5. 自動恢復 示例 6. 擴展和縮容 示例 示例 一、ReplicaSet ReplicaSet 是 Kubernetes 中的一個核心控…

python中redis操作整理

下載redis命令 pip install redis 連接redis import redis # host是redis主機&#xff0c;需要redis服務端和客戶端都起著 redis默認端口是6379 pool redis.ConnectionPool(hostlocalhost, port6379,decode_responsesTrue) r redis.Redis(connection_poolpool)操作字符串 …

自然語言處理入門4——RNN

一般來說&#xff0c;提到自然語言處理&#xff0c;我們都會涉及到循環神經網絡&#xff08;RNN&#xff09;&#xff0c;這是因為自然語言可以被看作是一個時間序列&#xff0c;這個時間序列中的元素是一個個的token。傳統的前饋神經網絡結構簡單&#xff0c;但是不能很好的處…

數據結構之鏈表(雙鏈表)

目錄 一、雙向帶頭循環鏈表 概念 二、哨兵位的頭節點 優點&#xff1a; 頭節點的初始化 三、帶頭雙向鏈表的實現 1.雙鏈表的銷毀 2.雙鏈表的打印 3.雙鏈表的尾插和頭插 尾插&#xff1a; 頭插&#xff1a; 4.雙鏈表的尾刪和頭刪 尾刪&#xff1a; 頭刪&#xff1a; …

ASP3605同步降壓調節器——滿足汽車電子嚴苛要求的電源芯片方案

ASP3605高效同步降壓調節器&#xff0c;通過AEC-Q100 Grade1認證&#xff0c;輸入電壓4V至15V&#xff0c;輸出電流5A&#xff0c;峰值效率94%。車規級型號ASP3605A3U支持-40C至125C工作溫度&#xff0c;適用于ADAS、車載信息娛樂系統等場景。 面向汽車電子的核心功能設計 1. …

vue3+Ts+elementPlus二次封裝Table分頁表格,表格內展示圖片、switch開關、支持

目錄 一.項目文件結構 二.實現代碼 1.子組件&#xff08;表格組件&#xff09; 2.父組件&#xff08;使用表格&#xff09; 一.項目文件結構 1.表格組件&#xff08;子組件&#xff09;位置 2.使用表格組件的頁面文件&#xff08;父組件&#xff09;位置 3.演示圖片位置 ele…

[特殊字符]1.2.1 新型基礎設施建設

&#x1f680; 新型基礎設施建設全解析 &#x1f31f; 核心概念與定義 維度詳細內容定義以新發展理念為引領&#xff0c;以技術創新為驅動&#xff0c;以信息網絡為基礎&#xff0c;提供數字轉型、智能升級、融合創新服務的基礎設施體系。提出背景2018年中央經濟工作會議首次提…

SQL Server數據庫慢SQL調優

SQL Server中慢SQL會顯著降低系統性能并引發級聯效應。首先&#xff0c;用戶直接體驗響應時間延長&#xff0c;核心業務操作&#xff08;如交易處理、報表生成&#xff09;效率下降&#xff0c;導致客戶滿意度降低甚至業務中斷。其次&#xff0c;資源利用率失衡&#xff0c;CPU…

【安全運營】安全運營關于告警降噪的一些梳理

目錄 前言一、智能技術層面1、機器學習和 AI 模型訓練2、攻擊成功判定 二、多源關聯分析1、多源設備關聯&#xff08;跨設備日志整合&#xff09;2、上下文信息增強 三、業務白名單和策略優化1、動態白名單機制2、閾值和規則調整 四、自動化和流程化1、告警歸并與去重2、同類型…

逆向中常見的加密算法識別

1、base64及換表 base64主要是將輸入的每3字節&#xff08;共24bit&#xff09;按照每六比特分成一組&#xff0c;變成4個小于64的索引值&#xff0c;然后通過一個索引表得到4個可見的字符。 索引表為一個64字節的字符串&#xff0c;如果在代碼中發現引用了這個索引表“ABCDEF…

《UNIX網絡編程卷1:套接字聯網API》第2章 傳輸層:TCP、UDP和SCTP

《UNIX網絡編程卷1&#xff1a;套接字聯網API》第2章 傳輸層&#xff1a;TCP、UDP和SCTP 2.1 傳輸層的核心作用與協議選型 傳輸層是網絡協議棧中承上啟下的核心層&#xff0c;直接決定應用的通信質量。其主要職責包括&#xff1a; 端到端通信&#xff1a;屏蔽底層網絡細節&am…

Eclipse 創建 Java 類

Eclipse 創建 Java 類 引言 Eclipse 是一款功能強大的集成開發環境(IDE),被廣泛用于 Java 開發。本文將詳細介紹如何在 Eclipse 中創建 Java 類,包括配置開發環境、創建新項目、添加類以及編寫類代碼等步驟。 配置 Eclipse 開發環境 1. 安裝 Eclipse 首先,您需要在您…