---
title: '【教學】🚀 SSE、WebSocket與Polling大PK!實時長連接通訊技術萌新指南 ✨!'
disqus: hackmd
---
# 【教學】🚀 SSE、WebSocket與Polling大PK!實時長連接通訊技術萌新指南 ✨!

## 🌟 摘要
嘿!想知道怎麼讓你的網站像聊天室一樣即時更新嗎?🤔
本篇文章要來解密三種實時通訊技術:
* **Server-Sent Events (SSE)**
* **WebSocket**
* **Polling**
我們會用最白話的方式告訴你它們到底在幹嘛、什麼時候該用哪一個,還有維護起來會不會讓你想哭 😭😭😭
## 💡 引言
現在的WEB APP都可能遇到要求「即時」更新的功能。
⚡⚡新訊息要馬上彈出來、股價、幣種行情要即時跳動、聊天室訊息要秒出現!但是要怎麼選擇合適的技術來實現這些需求呢?
其實這大段時間,提起這種技術,很多人都會陷入困惑:
- 「WebSocket 我知道有這東西,聽起來很厲害,但好像很複雜?」🤯
- 「Polling 實作很簡單,但會不會太耗資源?」😰
- 「SSE 是什麼?聽都沒聽過!」🙃
**好啦,開始劃重點!** 📝
很多人都誤會 SSE 和 WebSocket 一樣複雜,但其實 SSE 根本就省事太多了!它基於標準 HTTP,瀏覽器還內建重連功能!
---
## 🏆 學術界都說讚!權威研究報告出爐
在開始之前,先給大家看個超厲害的研究報告!📊
**瑞典布萊金理工學院** 的學者們做了一個超詳細的性能測試(沒錯,就是那種很嚴肅的學術研究 🤓),他們比較了這幾種技術的真實表現:
🔗 研究報告:
[《Performance comparison of XHR polling, Long polling, Server sent events and Websockets》](https://www.diva-portal.org/smash/get/diva2:1133465/FULLTEXT01.pdf)
- **TCP連接數據** (第26頁):XHR會導致連接數激增(高達289個連接),而其他技術保持在100個連接
- **研究結論** (第42-43頁)
- **性能測試結果** (第24-37頁)
### 📈 驚人的發現:
- **TCP連接大爆炸** 💥:傳統的XHR Polling 會產生高達 **289個連接**!而其他技術只需要100個左右
- **效能冠軍揭曉** 🥇:報告第43頁直接下結論:
> 💬 "Websockets and Server sent events were measured to be the highest performing of the studied technologies."
>
翻譯:WebSocket 和 SSE 就是本次比較雙冠王!🎉
### 性能比較表
| 技術 | 延遲 | 頻寬使用 | CPU使用 | 服務器負載 | 成本與擴展性 |
|------|------|----------|----------|------------|--------------|
| **HTTP Polling** | 高(受輪詢間隔限制) | 最高(每次完整HTTP請求) | 中 | 高(大量TCP連接) | 差(高併發連接爆炸) |
| **SSE** | 低(即時推送) | 低(僅傳輸新資料) | 低 | 中(單向長連接) | 佳(標準HTTP) |
| **WebSocket** | 最低(全雙工) | 最低(最小幀開銷) | 低 | 中(需維護連接) | 中(需特殊配置) |
## 🔄 HTTP Polling:老派但實用的笨方法
### 🤔 什麼是 Polling?
就是最簡單粗暴的方法啦!想像他是個很黏人的小小孩,每隔5秒就問媽媽「有新訊息嗎?有新訊息嗎?有新訊息嗎?」🥺
你的網頁就是那個小鬼,Server 就是覺得他很吵卻又一臉無奈的馬麻... 😅
### ⚙️ 怎麼實作?
超級簡單!用我們熟悉的工具就行:
- 拿出你的 `fetch()` 或 `Axios` 📞
- 設個定時器 `setInterval()` ⏰
- 每隔幾秒戳一下伺服器:「欸欸欸,有更新嗎?」
### 🔍 底層到底發生了什麼?
每次問問題的時候:
- 🤝 建立全新的 TCP 連線(握手)
- 📤 送出完整的 HTTP 請求
- 📥 接收回應
- 👋 關閉連線(掰掰)
- ⏱️ 等個幾秒...然後重複循環!
### 然後... 😰 問題來了...
如果你的瀏覽器有30個分頁同時開著,每個都在問「有更新嗎?」,伺服器就會:
- **崩潰邊緣** 💥:連線數量爆炸增長
- **荷包大失血** 💸:每次後端都要處理完整的 HTTP 請求
這其實和💥**DDoS**💥是差不多的行為,拜託一定要慎用!
但如果你的資料更新頻率超低(比如每5~10分鐘才更新一次天氣),那 Polling 其實還OK啦~ 🌤️
---
## 📡 SSE:簡單容易上手!建置成本最低的長連接!
### 💖 為什麼選 SSE?
- **HTTP 就是王道** 👑:不需要特殊伺服器,現有的就能用
- **一條連線走天下** 🛣️:建立一次連線就能一直用
- **瀏覽器是暖男** 🥰:自動幫你處理重連,不用自己寫Message Queue
- **最現代的解決方案** 🚀:使用HTML 5專門的 `EventSource` API,可穿透大多數代理和防火牆
### 🛠️ 怎麼用 SSE?
瀏覽器內建就有:
```javascript
// 就這麼簡單!🎉
const eventSource = new EventSource('/api/sse?token=your-token');
eventSource.onmessage = function(event) {
console.log('收到新訊息啦!', event.data);
// 在這裡更新你的 UI ✨
};
// 自動重連?瀏覽器幫你搞定!😎
```
不過要特別注意喔,根據瀏覽器相容支援表來看
目前比較新版本的 Android Chrome才有支援,iOS Safari則沒問題!

### 🔧 實作細節大揭密
- **單向溝通** 📤:只有伺服器可以推送給你(但通常這就夠了)
- **文字格式** 📝:傳輸純文字資料,通常是 JSON
- **Token 問題** 🎫:Header 放不了 token,要用 query string 或 cookie
- **自動重連** 🔄:斷線了?瀏覽器自動幫你重連!
- **需心跳檢測** 💖:每秒後端最好都傳個ping訊息防止斷開!
- **事件 ID** 🆔:有 `Last-Event-ID` 機制,重連後只拿新訊息
- **輕微延遲** ⏱️:走 HTTP chunked 傳輸,比 WebSocket 慢個1-100ms(但感覺不出來啦~)
### 🎯 最適合的場景
- **通知系統** 🔔:新訊息、系統警告(1-100ms 延遲完全不影響)
- **即時儀表板** 📊:股價、監控數據(人眼根本感覺不出來,除非真的要精準)
- **後台管理系統** 🖥️:各組運營資料更新(單向推送就夠了)
- **直播數據** 📺:觀看人數、彈幕統計(不需要毫秒級準確)
---
## 🔌 WebSocket:雙向溝通霸權
### 🚀 WebSocket 的超能力
- **全雙工通訊** ⚽:客戶端和伺服器都能隨時發消息
- **速度超快** ⚡:建立連線後,開銷超級小
- **支援二進位** 🔢:不只文字,圖片、檔案都能傳
- **協議升級** 🎭:從 HTTP 搖身變成 WebSocket
### 🛠️ 怎麼使用?
```javascript
// 建立 WebSocket 連線
const ws = new WebSocket('wss://your-server.com/socket');
ws.onopen = function() {
console.log('連線成功!可以開始聊天了 🎉');
ws.send('Hello Server! 👋');
};
ws.onmessage = function(event) {
console.log('收到回覆:', event.data);
};
ws.onclose = function() {
console.log('連線斷了...要重連嗎? 😥');
// 原生的websocket這裡要自己寫重連邏輯... 😅
};
```
### 但是...麻煩事也不少
**伺服器要特殊設定** 🔧:
- 需要支援 WebSocket 協議的伺服器
- 可能需要額外的服務或模組
- 負載均衡器也要特殊處理
**自己動手做** 🔨:
- 重連邏輯要自己寫
- 心跳檢測要自己處理
- 連線狀態要自己管理
**但是!有個超級英雄拯救了一切!**

### 🌟 Socket.IO 的魔法功能:
- **自動重連** 🔄:斷線了?自動重連!不用你操心!
- **心跳包** 💓:自動幫你維持連線活躍
- **降級處理** 🎭:WebSocket 不行?自動降級到 Long Polling!
- **房間系統** 🏠:輕鬆實現群組聊天、分頻道推送
- **事件驅動** ⚡:用 `emit` 和 `on` 就能輕鬆溝通
- **跨平台** 🌍:瀏覽器、Node.js、手機 App 都支援
### 💻 Socket.IO 使用範例:
```javascript
// 客戶端 - 超級簡單!
import io from 'socket.io-client';
const socket = io('http://localhost:3000');
// 發送訊息
socket.emit('chat message', 'Hello World! 👋');
// 接收訊息
socket.on('chat message', (msg) => {
console.log('收到訊息:', msg);
});
// 加入房間
socket.emit('join room', 'room1');
// 連線狀態處理(自動處理,但你也可以監聽)
socket.on('connect', () => console.log('連線成功!🎉'));
socket.on('disconnect', () => console.log('斷線了,但會自動重連 😌'));
```
```javascript
// 伺服器端 - Node.js
const io = require('socket.io')(server);
io.on('connection', (socket) => {
console.log('用戶連線了!🎉');
// 處理聊天訊息
socket.on('chat message', (msg) => {
// 廣播給所有人
io.emit('chat message', msg);
// 或者只發給特定房間
// socket.to('room1').emit('chat message', msg);
});
// 處理房間加入
socket.on('join room', (room) => {
socket.join(room);
socket.to(room).emit('user joined', 'OOO加入了聊天!');
});
});
```
### 🎯 為什麼 Socket.IO 這麼受歡迎?
- **開發速度快** ⚡:複雜功能幾行代碼搞定,MVP能快速落地
- **穩定性強** 🛡️:自動處理各種邊緣情況
- **功能豐富** 🎁:房間、namespace、middleware都有
- **社群強大** 👥:文檔完整、範例超多
- **生產就緒** 🏭:大公司都在用,經過實戰考驗
所以說,雖然原生 WebSocket 有些麻煩,但有了 Socket.IO,WebSocket 開發變得超級愉快!🎊
:::info
但別忘了這套東西可是前後端都要同時使用哦!
Java Spring Boot、Golang、Rust都有對應的版本可以使用!
而前端大多時候就只要選Latest就行啦~
:::
**網路環境挑剔** 🌐:
- 有些代理或防火牆會擋 WebSocket
- 企業網路環境可能有限制
### 🎯 最適合的場景
- **即時通訊** 💬:Messenger、Discord(需要雙向+超低延遲)
- **多人遊戲** 🎮:需要毫秒級反應的即時互動
- **協同編輯** ✏️:Google Docs、Figma(多人同步編輯)
- **即時交易** 📈:高頻交易系統(每毫秒都是錢!)
## 技術選擇指南
### 📊 實時通訊技術選擇決策樹
```
Q1: 需要雙向通訊嗎?(客戶端是否需要頻繁向服務發送消息?)
├── ✅ 是 → Q2
└── ❌ 否 → Q3
Q2: 是否需要極低的延遲和大量消息交換?
├── ✅ 是 → 🔌 推薦使用 WebSocket
└── ❌ 否 → Q3
Q3: 環境是否涉及多個分頁同時打開?
├── ✅ 是 → Q4
└── ❌ 否 → Q5
Q4: 是否關注資源效率和簡化的維護?
├── ✅ 是 → 📡+ 推薦使用 SSE + SharedWorker
└── ❌ 否 → Q5
Q5: 是否需要即時更新?(秒級或分鐘級響應)
├── ✅ 是 → 📡 推薦使用 SSE
└── ❌ 否 → 🔄 使用簡單的 Polling 即可
```
### 🔄 適合使用Polling的場景
- 數據更新頻率和粒度都極低(如每五分鐘至十分鐘以上才更新)
- 簡單實踐優先於效能,但通常成本不一定是最低,特別是瀏覽器記憶體比較危險
- 不需要即時性
- 後端架構難以支持長連接
### 📡 適合使用SSE的場景
- 服務到客戶端的單向通訊需求
- 需要即時通知或更新,且須採成本最低路線
- 希望利用標準HTTP基礎設施
- 不考慮手機版 (Safari iOS和火狐可用但Chrome不行)
- **實務應用**:通知系統、實時數據儀表板、即時行情、天氣更新等
### 🤝 適合使用WebSocket的場景
- 雙向通訊需求(客戶端頻繁發送消息)
- 極低延遲要求
- 大量訊息交換
- 有考慮配置專門的WebSocket服務
- **實務應用**:聊天室、多人遊戲、協同編輯工具(Figma、社群共筆工具)等
---
## 🎯 總結
在選擇實時通訊技術時,每種方案都有其適用場景:
### 🔄 HTTP Polling
- **適用場景**:低頻更新、簡單實現優先
- **劣勢**:多分頁環境下連接數量激增(🔄×30)
- **維護成本**:低複雜度,但高服務器負載
### 📡 SSE (Server-Sent Events)
- **適用場景**:單向通知、實時儀表板、風險警報
- **優勢**:標準HTTP協議、瀏覽器原生重連、低維護成本
- **最佳實踐**:📡+ SSE結合SharedWorker實現多分頁共享單一連接
### 🔌 WebSocket
- **適用場景**:聊天室、雙向頻繁通訊、協同編輯
- **優勢**:全雙工通訊、低延遲、二進制支持
- **劣勢**:需專門服務器、手動重連邏輯、防火牆穿透挑戰
**對於運營後台這類多分頁環境,📡+ SSE結合SharedWorker提供了明顯的優勢**:
- ⬇️ **顯著減少服務器連接數**(從30降至1,減少97%)
- 🔔 **提供更一致、更可控的通知體驗**(主分頁控制聲音)
- 🚀 **避免多分頁環境中的資源競爭和重複工作**
- ⚡ **保持近乎實時的推送能力,無需複雜的WebSocket維護**
對於大多數通知、風控警報和數據更新場景,特別是在多分頁環境下,📡 **SSE提供了更優的性能/維護比**。當然,如果需要客戶端到服務的頻繁通訊,有條件的話則🔌 **WebSocket仍然是更佳選擇**。
---
## 參考來源
### Server-Sent Events (SSE)
- **MDN Web Docs - Server-Sent Events**:[Server-sent events - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events)
- **WHATWG 標準 - Server-Sent Events**:[HTML Standard](https://html.spec.whatwg.org/multipage/server-sent-events.html)
- **MDN Web Docs - EventSource API**:[EventSource - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)
### WebSocket
- **MDN Web Docs - WebSocket API**:[The WebSocket API (WebSockets) - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API)
- **WHATWG 標準 - WebSocket**:[WebSockets Standard](https://websockets.spec.whatwg.org/)
### SharedWorker
- **MDN Web Docs - SharedWorker**:[SharedWorker - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker)
- **MDN Web Docs - 使用 Web Workers**:[Using Web Workers - Web APIs | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers)
---
###### tags: `VueJS` `Vue3` `websocket` `SSE` `polling` `SocketIO` `APP開發` `跨平台APP開發` `前端開發` `Web Development`