基礎設施練習題 (Practice - Infrastructure)
Related Concepts
- 11-Infrastructure/01-API-Gateway
- 11-Infrastructure/02-Load-Balancer
- 11-Infrastructure/03-Container
- 11-Infrastructure/04-Serverless
- 11-Infrastructure/05-CDN
| 概念 | 預設做法 | 關鍵點 |
|---|---|---|
| Gateway vs LB | LB 分流(L4/L7)、Gateway 路由(L7 懂業務) | GW 認證、服務授權 |
| Gateway SPOF | 多實例 + 前掛 LB(無狀態) | 限流計數器存共享 Redis |
| L4 vs L7 LB | 一般 HTTP → L7;WebSocket/長連線 → L4 | L7 終止連線會破壞持久連線 |
| Sticky Session | 過渡方案,理想把 session 外移 Redis | stateless 才好水平擴展 |
| VM vs 容器 | 90% 用容器;強隔離/不同 OS 才 VM | 共用 kernel(namespace/cgroups) |
| 容器自癒 | Deployment + liveness probe | readiness 控制是否接流量 |
| Serverless 時機 | 流量峰谷明顯 / 事件驅動 / 排程 | 15 分上限、Cold Start、嚴格無狀態 |
| Lambda DB 連線 | RDS Proxy / PgBouncer 或 DynamoDB | 千個並發打爆 DB 連線上限 |
| CDN 本質 | 地理分散的 read-through 快取(空間換時間) | 就近 Edge 命中、源站只服務 miss |
| CDN 失效首選 | Hash Busting + 長 TTL(immutable) | 別用短 TTL 求即時、會打爆源站 |
| 多層快取 | Edge → Regional/Shield → Origin | Shield 收斂回源、防 thundering herd |
| 什麼該走 CDN | 靜態資源 / 高頻共享內容 | 每人不同的動態回應別塞 CDN |
Part 1:API Gateway
Q1(Recall):API Gateway 解決了微服務架構的什麼問題?列出三項職責。
沒有 Gateway 時,橫切關注點在每個服務重複實作、客戶端要認得每個服務、內部拓撲外露。Gateway 是統一入口,集中處理:
- 請求路由(依路徑/method/header 轉發到對應服務)
- 認證(驗 JWT 簽名/有效期,解析用戶資訊給後端)
- 限流(按 IP/API key,超過回 429)
其他:SSL 終止、請求/回應轉換、請求聚合、快取。
Q2(Recall):API Gateway 和 Load Balancer 有什麼差別?
| 維度 | Load Balancer | API Gateway |
|---|---|---|
| 層次 | L4(TCP/UDP)/ L7 | L7(懂 HTTP 語義) |
| 職責 | 流量分散、高可用 | 路由、認證、限流、轉換 |
| 懂業務 | ❌ | ✅ |
LB 是流量分發器,Gateway 是智慧路由器。通常一起用:LB 把流量分到多個 Gateway 實例,Gateway 再依內容路由到後端。
Q3(Application):你的 API Gateway 多實例部署後,付費用戶發現可以超過 rate limit。為什麼?怎麼修?
限流計數器存在各實例本地 → A 實例看到 50 個請求,B 實例不知道 → 用戶分散打到不同實例就繞過了限制。
解法:把限流計數器存在共享的 Redis / Memcached,所有 Gateway 實例查同一份計數。這也是為什麼 Gateway 設計成無狀態(路由規則在設定/DB、限流狀態在 Redis)。
Q4(Application):Web 端和行動端對同一份資料的需求差很大(Web 要豐富、Mobile 要精簡)。怎麼設計 Gateway?
用 BFF(Backend for Frontend)模式:為不同客戶端維護各自的 Gateway。
- Web BFF:大量聚合,回傳豐富 JSON
- Mobile BFF:回傳精簡欄位省流量
- Public API Gateway:嚴格版本控制、向後相容(給第三方)
每個 BFF 由對應前端團隊維護,後端微服務不變。代價是多個 Gateway 要維護,小團隊用統一 Gateway 即可。
Q5(Analysis):認證應該在 Gateway 還是在服務裡做?為什麼不是非此即彼?
兩層都做,但做不同的事:
- Gateway 做認證(AuthN):驗 JWT 簽名和有效期,「這 token 是真的、沒過期」。純技術驗證、與業務無關 → 適合集中
- 服務做授權(AuthZ):「這個用戶能不能看這筆訂單」需要查 DB,Gateway 沒有這個業務 context
Gateway 可做粗粒度授權(路徑需要 admin role),細粒度資料授權(資源屬不屬於這個用戶)留在服務。一句話:Gateway 保證你是你說的人,服務決定你能做什麼。
Part 2:Load Balancer
Q6(Recall):Load Balancer 流量分配的「本質」是什麼?健康檢查為什麼重要?
流量分配的本質不是「平均」,而是讓整體吞吐量最大化、避免局部過載。太天真的分配會表面平均、實際不均(請求長短差異、節點規格差、GC/CPU 高峰)。
健康檢查讓「壞節點」在無人介入下自動隔離:定期探測(HTTP /health、TCP port),連續失敗就移出流量池,恢復後加回。是自動容錯的核心。
Q7(Recall):列出四種 LB 演算法,各自的盲點是什麼?
| 演算法 | 規則 | 盲點 |
|---|---|---|
| Round Robin | 依序輪流 | 請求長短差異大時實際不均 |
| Least Connections | 送給連線最少的 | 連線少 ≠ CPU 低 |
| IP Hash | 對 IP 雜湊固定後端 | NAT 出口集中不均;節點變動大搬遷 |
| Weighted Round Robin | 依性能給權重 | 靜態權重無法反映即時壓力 |
Q8(Application):系統有 WebSocket 即時聊天,要選 L4 還是 L7 LB?為什麼?
選 L4 LB。
- L4 工作在傳輸層(TCP/UDP),只管傳輸、不頻繁斷開重建,適合長連線
- L7 LB 會終止連線再建新連線,破壞 WebSocket 的持久連線
速答法則:WebSocket / 持久連線 → L4;一般 HTTP 流量 → L7(L7 提供 URL/Header/Method 的靈活路由)。
Q9(Analysis):用 Sticky Session 解決「狀態存在應用伺服器記憶體」的問題,有什麼風險?更好的做法是什麼?
Sticky Session(cookie / IP hash 讓用戶固定打同一台)的風險:
- 流量分佈不均(黏在熱門節點)
- 節點掛掉 → session 直接消失
更好的做法:把 session 外移到 Redis 或 DB,讓應用層保持 stateless。這樣任何實例都能處理任何請求,水平擴展與容錯都自然。Sticky Session 是過渡方案,不是長期最優架構。
Q10(Application):在系統設計面試畫架構圖時,Load Balancer 該怎麼畫?
不要在每個服務前面都畫一個 LB(多餘、讓圖混亂)。較好做法:
- 乾脆省略不畫,只說「這些服務是水平擴展的」
- 或只在系統入口畫一個 LB 作為抽象層
LB 本身也要避免 SPOF:實務上 ≥2 台 + failover + VIP / Anycast,或直接用雲端托管 LB(內建高可用)。
Part 3:Container
Q11(Recall):VM 和容器的根本差異是什麼?容器靠什麼做隔離?
VM 模擬整台電腦含獨立 kernel;容器共用宿主機 OS 核心,只隔離應用與 library。
- namespace:每個容器有自己的行程空間、網路、檔案系統視圖
- cgroups:限制 CPU / 記憶體
| 維度 | VM | 容器 |
|---|---|---|
| 啟動 | 幾分鐘 | 幾秒(幾百毫秒) |
| 記憶體 | 幾 GB | 幾十~幾百 MB |
| 隔離 | 完整 kernel | 行程層、共用 kernel |
Q12(Recall):Kubernetes 的 Pod、Deployment、Service、HPA 各自的角色?
- Pod:最小部署單位,1+ 容器共用網路/儲存。短暫的,不存持久狀態
- Deployment:部署無狀態服務,「維持 N 個健康 Pod」,崩潰自動補、更新逐步替換
- Service:Pod IP 不固定 → 提供穩定網路端點,自動對應符合條件的 Pod
- HPA:依 CPU/記憶體/自訂指標自動增減 Pod 數
Q13(Application):面試官問「這個 API 服務怎麼擴展?」用容器怎麼回答?
「把 API service 容器化部署在 K8s 上,設 HorizontalPodAutoscaler:CPU > 70% 自動增加 Pod,流量退去自動縮回。因為服務是無狀態的(session 存 Redis),LB 可把請求打到任何 Pod,擴縮都是幾秒的事。」
這比「加更多伺服器」具體得多,也展示對現代部署的理解。
Q14(Analysis):容器要能快速擴展/替換,前提是什麼?把 session 存在容器本地記憶體會發生什麼事?
前提是服務必須無狀態(stateless)。
若把 session 存容器本地記憶體:① 第二個請求被 LB 打到容器 B,找不到 session → 用戶被登出 ② 容器 A 重啟 → 記憶體裡所有 session 全消失。
正確做法:狀態外部化 —— session→Redis、持久資料→DB、檔案→S3、設定→ConfigMap。容器本身是 ephemeral,隨時可停可重建,不帶走任何東西。
Q15(Analysis):liveness probe 和 readiness probe 的差別?為什麼兩個都需要?
- Liveness probe:「容器還活著嗎?」失敗 → 重啟容器
- Readiness probe:「容器準備好接流量了嗎?」失敗 → 從 Service 後端移除(不重啟)
兩者差別很重要:一個服務可能活著但還在暖機(此時不該接流量 → readiness 失敗但別重啟);或沒崩潰但連不到 DB(請求打過去也白打 → readiness 移除)。只有真的死掉才該 liveness 重啟。
Part 4:Serverless
Q16(Recall):Serverless 的 FaaS 和 BaaS 差在哪?Cold Start 是什麼?
- FaaS:程式碼以函式為單位、事件觸發、執行完釋放、按毫秒計費(Lambda)
- BaaS:託管後端服務以 API 呼叫(DynamoDB、Auth0、S3)
Cold Start:第一次或閒置太久後呼叫,供應商要分配容器、載入程式碼、初始化 runtime、跑初始化程式碼 → 額外延遲 300ms~3s(Java/.NET 較久,Python/Node 較快)。執行完容器保溫 5–15 分,期間請求直接重用 = Warm Start(無額外延遲)。
Q17(Application):用戶上傳圖片後要產生縮圖。為什麼這是 Serverless 的好場景?怎麼設計?
這是純事件驅動:有圖片上傳才觸發,沒有就不跑。
設計:S3 Event Notification → Lambda 函式讀原圖、產生多種尺寸、寫回 S3。不必維護常駐 worker,成本幾乎是零(除非有圖片進來)。Cold Start 多幾百毫秒在這種非同步場景完全無所謂。
Q18(Analysis):幾千個並發 Lambda 同時連 PostgreSQL,資料庫被打掛。為什麼?兩種解法?
Lambda 無狀態,每個實例各自建 DB 連線,又可瞬間擴展到幾千並發 → 超過 PostgreSQL 的連線上限(預設幾百),資料庫直接被打掛。
解法一:RDS Proxy / PgBouncer —— 連線池代理。Lambda 連到代理,代理用少數幾十個長連線服務上千個 Lambda 實例。
解法二:改用 DynamoDB —— 原生 Serverless DB,沒有連線概念、按請求計費,天然適合 Lambda。
Q19(Analysis):什麼工作負載不該用 Serverless?舉兩個並說明替代方案。
- 長時間任務 > 15 分(影片/音訊轉碼、大型資料處理)→ Lambda 有 15 分鐘硬上限,改用 EC2 / Spot Instance 上的 worker 接 SQS
- 低延遲、延遲穩定性要求高(P99 < 100ms、即時遊戲、高頻交易)→ Cold Start 不確定性是問題;可用 Provisioned Concurrency 緩解但要為閒置容量付費,失去優勢 → 用容器
其他:持續高流量(按毫秒計費比容器貴)、複雜狀態管理(WebSocket、連線池)。
Part 5:CDN
Q20(Recall):CDN 的本質是什麼?用一句話定位它解決的核心問題。
CDN 是一張地理分散的快取網路:把內容複製到全球離使用者最近的 Edge 節點,讓請求就近命中而不必跨海打到源站。
本質是用空間換時間 —— 把長距離往返換成短距離往返,同時把絕大多數流量擋在源站之外。
Q21(Recall):說明 Cache Hit 與 Cache Miss 的流程差異,CDN 的 hit ratio 目標大約是多少?
- Cache Hit:Edge 已有內容 → 直接回傳,源站完全無感。
- Cache Miss:第一個請求(或 TTL 過期)會「回源(origin fetch)」抓回來順手快取,後續同區請求變 hit。
目標是把 hit ratio 拉到 90%+。每個 Edge 快取獨立,第一個 miss 的人幫整區暖好快取。
Q22(Recall):解釋 Edge Node、PoP、Origin Server、Shield Cache 各自的角色。
- Edge Node:最靠近使用者、實際回應快取內容的伺服器。
- PoP(Point of Presence):一個地理據點(城市/IX),內含一群 Edge 節點。
- Origin Server:內容的權威來源(應用伺服器或 Blob Storage)。
- Shield / Regional Cache:Edge 與 Origin 之間的中間層,收斂回源請求。
Q23(Recall):列出四種 CDN 快取失效策略,並指出最推薦的是哪一種。
- TTL:設過期時間,過期才回源驗證。
- 版本號 / Hash Busting(
app.a1b2c3.js):最推薦,改檔即改 URL,可放心設超長 immutable TTL。 - Purge API:主動清除指定快取,即時但全球傳播需時間。
- Stale-While-Revalidate:先回舊快取、背景靜默更新,使用者不等待。
Q24(Application):你要設計 Instagram 的頭像/貼文圖片分發。怎麼用 CDN?快取失效怎麼處理?
上傳寫進 Blob Storage(S3),URL 帶內容 hash,前面掛 CloudFront。全球用戶就近 hit,源站只服務第一次 miss。
失效靠 hash busting:圖片更新就換 URL,舊快取自然作廢,可放心設超長 immutable TTL,完全不必 purge。
Q25(Application):前端部署如何用 CDN 做到「零等待、無需 purge」的更新?
每次 build 產生帶 hash 的 JS/CSS,設 Cache-Control: max-age=31536000, immutable 永久快取;HTML 入口設 no-cache / 短 TTL,總是拿到最新並指向新資產檔名。
改版時 HTML 一更新就引用新的 hash 檔,舊資產自然失效 —— 部署零等待、無需主動 purge。
Q26(Analysis):為什麼「把 TTL 設成幾秒來確保即時更新」是反模式?正解是什麼?
短 TTL 讓快取頻繁過期 → hit ratio 崩潰、回源流量暴增、源站被打爆,等於失去 CDN 的意義。
正解是 immutable + hash busting:內容不變的檔案設超長 TTL,要更新就換檔名/版本號。真要立即下架特定檔案(違規圖)才用 Purge API。
Q27(Analysis):幾百個 Edge 同時 cache miss,源站照樣被打爆。這是什麼問題?怎麼解?
這是 thundering herd / cache stampede:大量 Edge 同時 miss、全部直接回源。
解法是加一層 Regional / Shield Cache(Origin Shield) 收斂回源請求,把源站承受的回源 QPS 從「Edge 數量級」降到「物件數量級」(每個物件只回源一次)。這是大型 CDN 的標配多層快取(Edge → Shield → Origin)。
Q28(Recall):純動態內容(每人不同的 API 回應)不能快取,CDN 還能幫上忙嗎?
能 —— 加速的是傳輸路徑而非快取命中:① 就近 TLS 終結省一個跨海握手;② CDN 私有骨幹網路由比公網更短更穩;③ Edge 到源站的連線池重用。
這是「Dynamic Content Acceleration」。半動態內容(所有人一樣但會變)還可用短 TTL + SWR 或在 Edge Compute 拼個人化。
Q29(Recall):CDN 怎麼把使用者請求導到「最近」的 Edge 節點?說明兩種主流機制。
- Anycast:同一個 IP 在全球多個 PoP 廣播,網路層 BGP 路由自然把封包送到最近的 PoP(Cloudflare 用法)。
- DNS-based:權威 DNS 依使用者解析來源(EDNS Client Subnet)回傳最近 Edge 的 IP(傳統 Akamai 用法)。
本質都是「就近導流」,與全域負載平衡(GSLB)同源。
Q30(Recall):除了內容快取,CDN 還常提供哪些功能?至少列出三項。
- 動態內容加速:TCP 優化、就近 TLS 終結、骨幹網優化路由,縮短回源延遲。
- 安全防護:DDoS 吸收、WAF、Bot 防護、隱藏源站 IP。
- 壓縮與優化:Gzip / Brotli、圖片壓縮、自動轉 WebP/AVIF、自適應位元率。
- Edge Compute:在 Edge 節點跑輕量 Serverless 邏輯(A/B 分流、header 改寫、JWT 驗證)。
Q31(Recall):Edge Compute 和一般的 Serverless 有什麼關係與差異?
Edge Compute 本質是「跑在 CDN 節點上的 Serverless 函式」(Cloudflare Workers、Lambda@Edge),跑在離使用者最近的 Edge。
限制比一般 Lambda 更嚴格:更短的執行時間、更小的記憶體、無法存取完整 OS。適合 A/B 分流、header 改寫、JWT 驗證、地理路由等輕量邏輯。
Q32(Application):直播一場百萬人觀看的線上演唱會,怎麼用 CDN 扛住流量?
把影片切片(HLS / DASH segments)放到 CDN,幾百萬觀眾的流量由全球 Edge 節點就近吸收,源站只推一份流到 CDN。
突發流量峰由 Edge 承擔,源站對外頻寬與負載維持低檔;同一片段對所有觀眾相同、可容忍秒級延遲,天然適合快取。
| 問題 | 解法 |
|---|---|
| 微服務橫切關注點重複 | API Gateway 集中認證/限流/SSL/路由 |
| Gateway 是 SPOF | 多實例 + 前掛 LB(無狀態,計數器存 Redis) |
| 認證 vs 授權 | Gateway 認證、服務授權(粗粒度可在 GW) |
| 多客戶端需求差異大 | BFF 模式(Web BFF / Mobile BFF / Public) |
| WebSocket 選 LB | L4(L7 會破壞持久連線) |
| 狀態存應用伺服器記憶體 | 外移 Redis,服務 stateless(別靠 Sticky Session) |
| 面試畫 LB | 省略或入口畫一個,別每個服務都畫 |
| VM vs 容器 | 90% 容器;強隔離/不同 OS/legacy 才 VM |
| 容器崩潰 | Deployment + liveness probe 幾秒自癒 |
| liveness vs readiness | 活著重啟 vs 沒準備好移出 Service |
| 容器零停機更新 | 滾動更新 + migration 向後相容 + graceful shutdown |
| Serverless 時機 | 流量峰谷明顯 / 事件驅動 / 排程 / 邊緣 |
| Cold Start 緩解 | 快語言/小包/初始化移 handler 外/Provisioned Concurrency |
| Lambda DB 連線爆炸 | RDS Proxy / PgBouncer 或 DynamoDB |
| Serverless 成本 | 流量峰谷划算;持續高流量容器便宜 |
| vendor lock-in | handler 抽象層分離業務邏輯(只能緩解) |
| 跨海延遲 / 源站負載 | CDN 就近 Edge 命中(空間換時間),源站只服務 miss |
| CDN 快取失效 | Hash Busting(首選)+ 長 TTL;必要時 Purge API / SWR |
| 短 TTL 求即時 | 反模式,改 immutable + hash busting |
| thundering herd 回源 | Regional / Shield Cache 收斂回源(Edge→Shield→Origin) |
| 動態內容也想用 CDN | 加速傳輸(就近 TLS / 骨幹路由 / 連線重用),非快取 |
| CDN 掛掉 | fallback 到 Origin / multi-CDN / DNS 故障切換 |
| 什麼不該放 CDN | 每人不同、不可快取的動態回應 |