網路基礎練習題 (Practice - Networking)
Related Concepts
- 01-Networking/01-Network-Layers-and-Requests
- 01-Networking/02-TCP-vs-UDP
- 01-Networking/03-HTTP-and-HTTPS
- 01-Networking/04-API-Paradigms
- 01-Networking/05-Realtime-Protocols
- 01-Networking/06-Load-Balancing
- 01-Networking/07-Fault-Handling
| 決策 | 預設 | 替代 |
|---|---|---|
| 傳輸層 | TCP | 低延遲+可丟包+無瀏覽器 → UDP |
| API 範式 | REST | 靈活查詢 → GraphQL;內部高效 → gRPC |
| 即時推送 | SSE | 雙向 → WebSocket;P2P音視訊 → WebRTC |
| LB 類型 | L7 | WebSocket → L4 |
| LB 演算法 | Round Robin | 長連線 → Least Connections |
| 故障處理 | 重試 + 指數退避 + 抖動 | 持續失敗 → 熔斷器 |
網路層次與請求流程
Q1(Recall):系統設計面試中最重要的三個網路層次是什麼?各自的核心協定是?
- L3 網路層:IP — 路由、定址、封包轉送(best-effort)
- L4 傳輸層:TCP, UDP, QUIC — 端到端通訊、可靠性
- L7 應用層:HTTP, DNS, WebSocket, WebRTC — 應用程式通訊抽象
Q2(Recall):一個完整的 Web 請求(瀏覽器輸入網址到顯示頁面)經歷哪些步驟?
- DNS 解析:域名 → IP 位址
- TCP 三次握手:SYN → SYN-ACK → ACK
- HTTP 請求:客戶端發送 GET 請求
- 伺服器處理:查詢資料、準備回應(開發者唯一能控制的延遲)
- HTTP 回應:伺服器回傳內容
- TCP 四次揮手:FIN → ACK → FIN → ACK
Q3(Analysis):為什麼 HTTP keep-alive 和 HTTP/2 多路複用對效能很重要?它們解決了什麼問題?
沒有 keep-alive,每個 HTTP 請求都需要重新三次握手,帶來顯著延遲。
- HTTP/1.1 keep-alive:同一 TCP 連線發多個請求(序列化,有線頭阻塞)
- HTTP/2 多路複用:同一 TCP 連線並行多個請求,消除線頭阻塞
在設計需要持久連線的系統(SSE、WebSocket)時,連線狀態管理成本也需要特別考量。
傳輸層協定
Q4(Recall):TCP 和 UDP 各有哪些關鍵特性?標頭大小分別是?
TCP:面向連線、保證交付、維護順序、流量控制、壅塞控制,標頭 20–60 bytes
UDP:無連線、盡力而為、不保證順序、無流量控制,標頭 8 bytes
TCP 額外開銷大但可靠;UDP 輕量但可能丟包。
Q5(Application):以下場景各適合用 TCP 還是 UDP?說明原因。
(A) 銀行轉帳 API (B) 線上遊戲角色移動 (C) 影片串流 (D) 下載大型檔案
- (A) TCP:銀行交易不能丟包,必須可靠交付
- (B) UDP:遊戲要低延遲,偶爾丟一幀位置更新可以接受
- (C) UDP:影片串流可容忍少量丟包(卡頓比延遲更不可接受)
- (D) TCP:檔案下載必須完整無缺,丟包需要重傳
Q6(Recall):在瀏覽器中使用 UDP 有什麼限制?如何在需要 UDP 但需支援瀏覽器的情況下設計?
瀏覽器只能透過 WebRTC 使用 UDP,無法直接使用原生 UDP。
支援瀏覽器的設計方案:
- 原生 App 用戶 → 使用真正的 UDP 串流
- 瀏覽器用戶 → 降級到批次 HTTP 串流(如 SSE 或 polling)
HTTP 與 HTTPS
Q7(Recall):以下 HTTP 方法哪些是冪等的?(A) GET (B) POST (C) PUT (D) DELETE (E) PATCH
冪等:(A) GET、(C) PUT、(D) DELETE
非冪等:(B) POST、(E) PATCH
冪等 = 多次呼叫結果和一次相同。GET 讀取不改狀態;PUT 覆寫結果相同;DELETE 刪了就是刪了。
Q8(Recall):401 和 403 的差異是什麼?
- 401 Unauthorized:「你是誰?」— 尚未驗證身份,需要提供憑證
- 403 Forbidden:「我知道你是誰,但你沒有權限」— 已驗證但沒有存取此資源的授權
Q9(Analysis):為什麼說「HTTPS 不代表請求內容可信」?請舉例說明錯誤做法和正確做法。
HTTPS 只加密傳輸通道,不保證請求內容是合法客戶端產生的。
❌ 錯誤:從 request body 讀取 user_id 做資料庫查詢
→ 攻擊者自行構造請求並修改 body 中的 user_id,可讀取任意用戶資料
✅ 正確:永遠從驗證過的 session/token(如 JWT 簽名、Cookie)取得用戶身份
API 範式比較
Q10(Recall):REST、GraphQL、gRPC 的預設選型策略是什麼?
- REST:外部 API 的預設選擇,簡單、靈活、易快取
- GraphQL:前端需靈活查詢且資料結構複雜時(避免 over/under-fetching)
- gRPC:內部微服務間通訊,二進位序列化(Protocol Buffers),吞吐量約 JSON 的 10 倍
策略:內部 gRPC + 外部 REST
Q11(Application):請將以下 API 設計改成 RESTful 風格:
/updateUser?id=5、/createOrder、/deleteComment?id=10
/updateUser?id=5→PUT /users/5或PATCH /users/5/createOrder→POST /orders/deleteComment?id=10→DELETE /comments/10
REST 原則:資源(名詞)+ HTTP 動詞,URL 裡不放動詞。
Q12(Analysis):一個社群媒體平台,首頁需要顯示用戶資料、最新貼文、推薦好友。你會選 REST 還是 GraphQL?為什麼?
GraphQL 更合適:
- 首頁需要多種資料類型(用戶、貼文、推薦),REST 需要多個 API 呼叫(under-fetching)
- 各個 client(手機/網頁)需要的欄位不同,GraphQL 讓各自請求精確需要的資料
- 前端團隊可以快速迭代頁面佈局而無需後端配合
但如果是面試中固定需求的題目,先說 REST 再提 GraphQL 作為選項也是好做法。
即時通訊協定
Q13(Recall):SSE、WebSocket、WebRTC 的方向性和底層傳輸分別是?
| 協定 | 方向 | 底層 |
|---|---|---|
| SSE | 單向(Server → Client) | HTTP/TCP |
| WebSocket | 雙向 | TCP(HTTP Upgrade) |
| WebRTC | P2P | UDP |
Q14(Application):以下場景應該選哪個即時通訊協定?(A) 拍賣平台出價更新 (B) 多人線上遊戲 (C) 視訊會議 (D) 股票報價顯示板
- (A) SSE:伺服器單向推送出價更新即可,不需要雙向
- (B) WebSocket:遊戲需要高頻雙向通訊(玩家操作 + 伺服器狀態)
- (C) WebRTC:音視訊 P2P 通話,低延遲 UDP
- (D) SSE:股票報價是伺服器推送,客戶端只需接收
Q15(Analysis):為什麼「沒有說明原因就在設計中使用 WebSocket」會被面試官扣分?
WebSocket 的隱藏成本很高:
- 基礎設施成本:客戶端到伺服器之間的每個元件(防火牆、代理、LB)都必須支援 WebSocket
- 有狀態連線:規模下需要大量設計配合(Session Affinity、橫向擴展複雜)
- HTTP Upgrade 後難以降級
正確做法:先考慮 SSE(夠嗎?),只有需要真正雙向高頻通訊時才用 WebSocket。
負載平衡
Q16(Recall):L4 和 L7 負載平衡器的核心差異是什麼?各自的適用場景?
- L4 LB(傳輸層):根據 IP/Port 路由,維護持久 TCP 連線,速度快,不理解 HTTP 內容 → 適合 WebSocket
- L7 LB(應用層):理解 HTTP,可根據 URL/header/cookie 路由,功能強但 CPU 消耗高 → 適合 HTTP 流量(預設)
Q17(Application):一個聊天服務使用 WebSocket,應選哪種 LB?哪種 LB 演算法?為什麼?
- LB 類型:L4 LB — WebSocket 需要持久 TCP 連線,L7 LB 會終止並重建連線破壞 WebSocket
- 演算法:Least Connections(最少連線)— WebSocket 是長連線,Round Robin 會讓舊伺服器積累所有連線,新加入的伺服器無法分到已建立的連線
Q18(Analysis):什麼情況下應該使用 CDN?什麼情況下用區域分片(Regional Partitioning)?
CDN:
- 靜態內容(圖片、影片、JS/CSS)全球分發
- 可快取性高、不需要個人化的資料
- 透過邊緣節點降低全球延遲
區域分片:
- 資料有地理性(使用者的資料只跟同區域用戶相關)
- 典型例子:Uber 叫車(台北用戶不需要紐約的司機資料)
- 讓計算和資料共址,大幅降低查詢延遲
故障處理模式
Q19(Recall):重試策略中為什麼需要「抖動(jitter)」?如果沒有抖動會發生什麼?
沒有抖動 → 大量客戶端在同一時間同步重試 → thundering herd(驚群效應):瞬間流量尖峰反而讓已經不健康的服務更不堪負荷。
加入隨機抖動讓重試時間錯開,分散請求,給伺服器恢復的時間。
面試關鍵字:「retry with exponential backoff and jitter」
Q20(Application):設計一個支付系統的重試機制。如何防止因網路問題重試導致的重複扣款?
使用冪等鍵(Idempotency Key):
POST /payments
headers: { "Idempotency-Key": "user_123_2026-04-20_order_456" }
body: { "amount": 100 }
伺服器:
- 收到請求 → 檢查是否已處理此 key
- 已處理 → 回傳相同結果,不重複扣款
- 未處理 → 處理並記錄 key
Key 組成:user_id + date + operation_type(識別同一「意圖」的重試)
Q21(Analysis):熔斷器的三個狀態是什麼?它解決了什麼問題?和簡單重試相比有何優勢?
三個狀態:
- Closed(正常):監控失敗次數,正常通過
- Open(跳閘):失敗超閾值後,立即拒絕所有請求,不嘗試呼叫
- Half-Open(測試):逾時後放一個測試請求,成功則復原,失敗則回到 Open
解決的問題:級聯故障(cascading failure)
下游服務崩潰時,持續重試只會讓問題更嚴重(驚群效應)
vs 簡單重試的優勢:
- 快速失敗:立即拒絕,不等逾時(用戶體驗更好)
- 減少下游壓力:不用更多請求壓垮已掙扎的服務
- 自動恢復:無需人工介入
- 防止整個系統崩潰,而不只是保護一個服務
| 問題 | 解法 | 關鍵點 |
|---|---|---|
| 暫時故障 | 指數退避重試 + 抖動 | jitter 防止 thundering herd |
| 重試副作用 | 冪等鍵 | user_id + date + operation |
| 級聯故障 | 熔斷器 | Closed → Open → Half-Open |