前端實(shí)時通信技術(shù)之HTTP輪詢、SSE、WebSocket、WebRTC詳解
前言
在Web開發(fā)中,我們經(jīng)常遇到需要“實(shí)時獲取最新數(shù)據(jù)”的場景:股票行情、聊天消息、語音識別、視頻通話……這些場景對通信技術(shù)的要求各不相同。
很多同學(xué)對這些技術(shù)的選型感到困惑:什么時候用輪詢?什么時候用SSE?WebSocket和WebRTC又有什么區(qū)別?
今天這篇文章,就帶大家徹底搞懂這幾種技術(shù)的原理、優(yōu)缺點(diǎn)和適用場景。
一、技術(shù)全景圖
先看一張總覽表,快速了解四種技術(shù)的核心差異:
| 技術(shù) | 通信方向 | 協(xié)議 | 實(shí)時性 | 復(fù)雜度 | 典型場景 |
|---|---|---|---|---|---|
| HTTP短輪詢 | 單向(客戶端請求) | HTTP | 差(有延遲) | 低 | 舊版消息通知 |
| HTTP長輪詢 | 單向(模擬推送) | HTTP | 一般 | 中 | 兼容性要求高的場景 |
| SSE | 單向(服務(wù)器→客戶端) | HTTP | 好 | 低 | 消息推送、股票行情 |
| WebSocket | 雙向(全雙工) | WS/WSS | 極好 | 中 | 聊天、游戲、實(shí)時語音識別 |
| WebRTC | 雙向(P2P媒體流) | UDP為主 | 極好(低延遲) | 高 | 音視頻通話、實(shí)時會議 |
二、HTTP輪詢:最原始的方式
1. 短輪詢(Short Polling)
工作原理:客戶端每隔一段時間(如1秒)主動向服務(wù)器發(fā)起HTTP請求,詢問是否有新數(shù)據(jù)。
// 短輪詢示例
setInterval(async () => {
const response = await fetch('/api/messages');
const data = await response.json();
updateUI(data);
}, 1000); // 每秒請求一次優(yōu)點(diǎn):
實(shí)現(xiàn)極其簡單
兼容所有瀏覽器和服務(wù)器
缺點(diǎn):
大量無效請求,浪費(fèi)資源
實(shí)時性差(延遲 = 輪詢間隔)
服務(wù)器壓力大
適用場景:幾乎沒有。已被更好的方案取代。
2. 長輪詢(Long Polling)
工作原理:客戶端發(fā)起請求后,服務(wù)器“掛起”這個請求,直到有新數(shù)據(jù)或超時才返回??蛻舳耸盏巾憫?yīng)后立即發(fā)起下一次請求。
// 長輪詢示例
async function longPoll() {
const response = await fetch('/api/wait-for-messages');
const data = await response.json();
updateUI(data);
longPoll(); // 立即發(fā)起下一次
}
longPoll();優(yōu)點(diǎn):
相比短輪詢,無效請求少
兼容性好,可在不支持SSE/WebSocket的環(huán)境使用
缺點(diǎn):
服務(wù)器需要維持大量掛起連接
實(shí)現(xiàn)比短輪詢復(fù)雜
仍有HTTP頭開銷
適用場景:需要兼容老舊瀏覽器的實(shí)時推送場景。
三、SSE(Server-Sent Events):輕量級服務(wù)器推送
什么是SSE?
SSE是HTML5標(biāo)準(zhǔn)的一部分,允許服務(wù)器單向向客戶端推送數(shù)據(jù)。它基于HTTP協(xié)議,使用簡單。
工作原理
客戶端通過EventSourceAPI建立連接,服務(wù)器保持連接打開,隨時可以推送數(shù)據(jù)。
// 客戶端代碼
const eventSource = new EventSource('/api/stream');
eventSource.onmessage = (event) => {
console.log('收到數(shù)據(jù):', event.data);
};
eventSource.onerror = (error) => {
console.error('連接出錯:', error);
};
// 關(guān)閉連接
// eventSource.close();
javascript
// 服務(wù)端代碼(Node.js + Express示例)
app.get('/api/stream', (req, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
// 每秒推送一條消息
const interval = setInterval(() => {
res.write(`data: ${JSON.stringify({ time: Date.now() })}\n\n`);
}, 1000);
req.on('close', () => clearInterval(interval));
});優(yōu)點(diǎn)
簡單:基于HTTP,無需特殊協(xié)議
自動重連:連接斷開后瀏覽器自動嘗試重連
輕量:比WebSocket更輕量,適合單向推送
支持自定義事件:可以推送不同類型的事件
缺點(diǎn)
單向:只能服務(wù)器→客戶端,客戶端無法通過同一連接發(fā)送數(shù)據(jù)
連接數(shù)限制:瀏覽器限制同域名下6個左右并發(fā)連接
不支持二進(jìn)制數(shù)據(jù):只能傳輸文本(通常用JSON或純文本)
適用場景
股票行情、加密貨幣價格
消息通知中心
日志實(shí)時輸出
AI對話流式輸出(配合打字機(jī)效果)
手動開關(guān)的語音轉(zhuǎn)文字結(jié)果推送
典型產(chǎn)品
微信網(wǎng)頁版的消息通知、微博實(shí)時提醒
四、WebSocket:真正的雙向?qū)崟r通信
什么是WebSocket?
WebSocket是一種全雙工通信協(xié)議,在單個TCP連接上實(shí)現(xiàn)客戶端和服務(wù)器之間的雙向?qū)崟r通信。
工作原理
通過HTTP升級握手建立連接,之后切換為WebSocket協(xié)議,保持長連接。
javascript
// 客戶端代碼
const ws = new WebSocket('wss://example.com/socket');
ws.onopen = () => {
console.log('連接已建立');
ws.send(JSON.stringify({ type: 'join', room: 'chat' }));
};
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('收到消息:', data);
};
ws.onerror = (error) => {
console.error('WebSocket錯誤:', error);
};
ws.onclose = () => {
console.log('連接已關(guān)閉');
};javascript
// 服務(wù)端代碼(Node.js + ws庫示例)
import { WebSocketServer } from 'ws';
const wss = new WebSocketServer({ port: 8080 });
wss.on('connection', (ws) => {
console.log('客戶端已連接');
ws.on('message', (data) => {
console.log('收到:', data.toString());
// 廣播給所有客戶端
wss.clients.forEach(client => {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
ws.send('歡迎加入聊天室!');
});優(yōu)點(diǎn)
真正的雙向?qū)崟r:客戶端和服務(wù)器可以隨時互相發(fā)送消息
低延遲:連接建立后,消息直接傳輸,無需HTTP頭
高效:相比HTTP輪詢,大幅減少網(wǎng)絡(luò)開銷
支持二進(jìn)制:可以傳輸二進(jìn)制數(shù)據(jù)(如音頻流)
缺點(diǎn)
實(shí)現(xiàn)復(fù)雜:需要處理心跳、斷線重連、消息確認(rèn)等
協(xié)議特殊:需要服務(wù)器支持WebSocket協(xié)議
負(fù)載均衡麻煩:長連接對負(fù)載均衡器有特殊要求
防火墻可能攔截:某些網(wǎng)絡(luò)環(huán)境可能阻斷WebSocket
適用場景
即時通訊(微信、QQ)
在線游戲(實(shí)時位置同步)
協(xié)同編輯(多人同時編輯文檔)
實(shí)時語音轉(zhuǎn)文字(邊說邊出字)
實(shí)時數(shù)據(jù)看板(監(jiān)控系統(tǒng))
典型產(chǎn)品
微信(部分功能)、Slack、騰訊文檔
五、WebRTC:P2P音視頻通信
什么是WebRTC?
WebRTC(Web Real-Time Communication)是一個支持瀏覽器之間直接進(jìn)行音視頻通信的開源項目。它允許在不安裝插件的情況下實(shí)現(xiàn)點(diǎn)對點(diǎn)(P2P)的音視頻通話。
核心組件
getUserMedia:獲取麥克風(fēng)/攝像頭權(quán)限,采集音視頻流
RTCPeerConnection:建立P2P連接,傳輸音視頻流
RTCDataChannel:傳輸任意數(shù)據(jù)(文件、文字等)
工作原理
WebRTC需要信令服務(wù)器(通常用WebSocket實(shí)現(xiàn))來交換連接信息,但媒體數(shù)據(jù)走P2P的UDP通道。
// 獲取麥克風(fēng)流
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true, // 回聲消除
noiseSuppression: true, // 噪聲抑制
autoGainControl: true // 自動增益
},
video: true
});
// 創(chuàng)建對等連接
const pc = new RTCPeerConnection();
// 添加本地流
stream.getTracks().forEach(track => {
pc.addTrack(track, stream);
});
// 接收遠(yuǎn)程流
pc.ontrack = (event) => {
remoteVideo.srcObject = event.streams[0];
};
// 創(chuàng)建offer(發(fā)起方)
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
// 通過信令服務(wù)器發(fā)送offer給遠(yuǎn)端優(yōu)點(diǎn)
極低延遲:基于UDP,無需服務(wù)器中轉(zhuǎn),延遲通常<400ms
P2P架構(gòu):節(jié)省服務(wù)器帶寬和計算資源
內(nèi)置音視頻處理:回聲消除、降噪、自動增益等
安全:強(qiáng)制加密(DTLS/SRTP)
缺點(diǎn)
實(shí)現(xiàn)極其復(fù)雜:需要處理STUN/TURN穿透、NAT、信令等
P2P不可靠:網(wǎng)絡(luò)環(huán)境差時需要TURN服務(wù)器中轉(zhuǎn)
連接建立慢:ICE候選收集、連接建立需要時間
瀏覽器兼容性:老瀏覽器不支持或支持不完整
適用場景
視頻會議(Zoom、騰訊會議)
語音通話(Discord)
實(shí)時互動直播
P2P文件傳輸
AI語音助手(實(shí)時對話場景)
典型產(chǎn)品
Google Meet、Zoom(Web版)、Discord
六、技術(shù)選型決策樹
根據(jù)您的具體需求,可以按照這個決策樹來選擇:
需要實(shí)時通信?
│
├─ 只需要服務(wù)器推送給客戶端?
│ │
│ ├─ 是 → SSE(簡單、輕量)
│ │
│ └─ 需要客戶端也能發(fā)送數(shù)據(jù)?
│ │
│ ├─ 文本/JSON數(shù)據(jù) → WebSocket
│ │
│ └─ 音視頻流 → WebRTC
│
└─ 需要極低延遲、P2P直連?
│
└─ 是 → WebRTC七、實(shí)戰(zhàn)場景對照表
| 場景 | 推薦技術(shù) | 原因 |
|---|---|---|
| 股票行情推送 | SSE | 單向推送,實(shí)現(xiàn)簡單 |
| 聊天室 | WebSocket | 雙向通信,實(shí)時性強(qiáng) |
| 視頻會議 | WebRTC | P2P低延遲,內(nèi)置音視頻處理 |
| 實(shí)時語音識別(邊說邊出) | WebSocket / WebRTC | 需要上傳音頻流+接收結(jié)果 |
| 按住說話轉(zhuǎn)文字 | HTTP + SSE(可選) | 一次性上傳,結(jié)果可推送可不推送 |
| 消息通知中心 | SSE | 單向推送,自動重連 |
| 協(xié)同編輯 | WebSocket | 雙向?qū)崟r同步 |
| AI對話流式輸出 | SSE 或 WebSocket | SSE更簡單,WebSocket更靈活 |
| 在線游戲 | WebSocket | 雙向?qū)崟r,延遲敏感 |
| 實(shí)時日志查看 | SSE | 單向推送,適合tail -f場景 |
八、總結(jié)
HTTP輪詢:老古董,除非需要兼容極老的瀏覽器,否則不要再用了。
SSE:如果你只需要服務(wù)器單向推送數(shù)據(jù),SSE是最簡單、最輕量的選擇。它的自動重連機(jī)制非常好用。
WebSocket:如果需要雙向?qū)崟r通信(客戶端和服務(wù)器都能隨時發(fā)消息),WebSocket是標(biāo)準(zhǔn)答案。它的生態(tài)最成熟。
WebRTC:如果要做音視頻通話或需要極低延遲的P2P通信,WebRTC是唯一的選擇。但復(fù)雜度最高,建議使用成熟的SDK(如聲網(wǎng)、騰訊云音視頻)。
一個常見誤區(qū):很多人以為SSE和WebSocket是競爭關(guān)系,其實(shí)它們解決的是不同問題。SSE解決"服務(wù)器推"的問題,WebSocket解決"互相推"的問題。兩者可以共存,各司其職。
選型原則:
選最簡單的能解決問題的方案
SSE能搞定就不要上WebSocket
WebSocket能搞定就不要上WebRTC
除非有充分理由,否則不要自己造輪子
總結(jié)
到此這篇關(guān)于前端實(shí)時通信技術(shù)之HTTP輪詢、SSE、WebSocket、WebRTC的文章就介紹到這了,更多相關(guān)前端HTTP輪詢、SSE、WebSocket、WebRTC內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript解析及序列化JSON的方法實(shí)例分析
這篇文章主要介紹了JavaScript解析及序列化JSON的方法,結(jié)合實(shí)例形式分析javascript針對json格式數(shù)據(jù)的解析、序列化等相關(guān)操作技巧,需要的朋友可以參考下2019-01-01
javascript中的document.open()方法使用介紹
document.open()方法打開一個新的文檔并用document.write()方法編寫文檔的內(nèi)容,下面有個不錯的示例,大家可以感受下2013-10-10
Javascript 浮點(diǎn)運(yùn)算的問題分析與解決方法
JavaScript 只有一種數(shù)字類型 Number ,而且在Javascript中所有的數(shù)字都是以IEEE-754標(biāo)準(zhǔn)格式表示的。 浮點(diǎn)數(shù)的精度問題不是JavaScript特有的,因?yàn)橛行┬?shù)以二進(jìn)制表示位數(shù)是無窮的2013-08-08
比JSON.stringify快兩倍的fast-json-stringify性能對比分析
這篇文章主要為大家介紹了比JSON.stringify快兩倍的fast-json-stringify性能對比分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12
JavaScript 中的 `==` 和 `===` 操作符詳解
在 JavaScript 中,== 和 === 是兩個常用的比較操作符,分別用于 寬松相等(類型轉(zhuǎn)換相等) 和 嚴(yán)格相等(類型和值必須相等) 的比較,理解它們的區(qū)別以及具體的比較規(guī)則對于編寫準(zhǔn)確和高效的代碼至關(guān)重要,需要的朋友可以參考下2024-09-09

