
在微服務架構中,應用程式不再是單一的泥球(Monolith),而是被切分成數十甚至上百個小型、自治的服務。這些服務需要協同合作來完成一個完整的業務需求,例如:一個「產品詳情頁」可能需要同時查詢商品基本資訊、價格、庫存、評價、個人購買歷史等。
問題是,這麼多服務要如何對外提供統一的入口?
而且,這些服務的實例位置(host + port)不斷變化,客戶端要怎麼找到它們?
答案就是:API Gateway 與 Service Discovery。
本篇文章將深入探討這兩個模式,並說明它們如何協同運作,成為微服務落地的應用程式基礎設施。
API Gateway 模式
背景與動機
想像你正在開發一個電商網站,產品詳情頁需要整合多種資訊:
- Product Info Service:商品基本資訊(名稱、作者、簡介)
- Pricing Service:價格資訊
- Inventory Service:庫存狀態
- Review Service:用戶評價
- Order Service:用戶的購買歷史
在單體式架構下,這些資料查詢可能只是幾個函式呼叫,但在微服務架構下,這些功能都拆分為獨立服務。結果就是:客戶端必須直接呼叫多個服務。
這樣的情境帶來了幾個問題:
- 多次網路通訊:對於行動網路或高延遲環境,體驗很差。
- 不同裝置需求不同資料:桌面端需要完整的資訊,行動端則只需要精簡版本。
- 服務實例動態變化:服務可能隨時擴容或縮容,位置會改變。
- 跨協議整合:有些內部服務可能不是 HTTP/REST,而是 gRPC 或訊息佇列。
為了解決這些問題,API Gateway 應運而生。
解決方案
API Gateway 是微服務架構中所有客戶端的統一入口。
- 可以將一個請求分發到多個後端服務(API Composition)。
- 可以根據不同客戶端,提供不同版本的 API(Backends for Frontends, BFF)。
- 可以進行安全控制(驗證、授權)。
- 可以進行協議轉換(HTTP → gRPC)。
- 可以整合流量控制(限流、熔斷、快取)。
【範例】
Netflix 的 API Gateway 就是個知名案例。它會根據不同的裝置(電視、手機、桌機)提供最佳化 API,確保效能與體驗。
API Gateway 的優點
- 隱藏後端服務的複雜性:客戶端只需要與 Gateway 溝通。
- 減少網路往返:一個 API 請求即可整合多個服務的資料。
- 支援多客戶端需求:桌機、手機、第三方應用都可以有專屬 API。
- 統一安全與流量管理:可整合 OAuth2、JWT、API Key 等機制。
- 簡化客戶端邏輯:不需知道各個微服務的細節。
API Gateway 的缺陷
- 單點瓶頸(Single Point of Failure):若 Gateway 掛掉,整個系統對外不可用。
- 額外延遲:所有請求都必須先經過 Gateway,多了一跳。
- 開發與維運複雜度:需要專門的團隊來維護 Gateway。
另外一個方案,Backend for Frontend (BFF)
在某些場景下,不同的客戶端需求差異非常大。
例如:
- Web 前端:需要完整的商品詳情。
- Mobile 前端:只需要標題、價格、庫存。
- 合作夥伴 API:只需要公開資料。
這時候,可以設計 多個 API Gateway,針對不同客戶端提供專屬 API。這就是 BFF 模式。
API Gateway 與其他模式的關係
- 與 Service Discovery 整合:Gateway 必須知道如何找到後端服務。
- 與 Circuit Breaker 搭配:防止單一服務失效影響整體。
- 與 API Composition / CQRS 搭配:支援跨服務查詢。
- 與 Observability 整合:集中收集日誌、追蹤與監控。
Service Discovery 模式
在單體架構中,服務之間的呼叫多半是函式呼叫,不需要「找位置」。
在傳統分散式架構中,服務通常部署在固定位置(IP:Port),可以寫死在設定檔中。
但是在微服務架構下:
- 服務實例數量會動態變化(自動擴縮容)。
- 服務 IP/Port 是動態分配的(Kubernetes Pod、Docker Container)。
- 服務可能隨時新增或移除。
因此,必須有一個「電話簿」來管理所有服務實例的位址,並且讓客戶端能找到正確的服務。這就是 Service Discovery。
Service Registry
Service Discovery 的核心是 Service Registry,它是一個資料庫,記錄所有服務實例的位置與狀態。
常見的 Service Registry:
- Netflix Eureka
- Consul
- Zookeeper
- Etcd
- Kubernetes 內建 Service Registry
下列將介紹各種不同的實作模型:
Client-side Discovery
實作方式:
- 客戶端(例如 API Gateway)先查詢 Service Registry。
- 取得可用的服務實例清單。
- 客戶端自己做 Load Balancing,選擇一個實例呼叫。
Server-side Discovery
實作方式:
- 客戶端只需要呼叫一個固定的 router(Load Balancer)
- Router 向 Service Registry 查詢,轉發請求到可用實例
Self Registration
實作方式:
- 服務自己在啟動時註冊到 Registry,關閉時自動移除。
- 範例:Spring Cloud + Eureka Client。
3rd Party Registration
實作方式:
- 由外部代理(Sidecar, Daemon, Orchestrator)來負責註冊。
- 範例:Kubernetes Service Controller。
每個模式的套用基本上都是有好有壞,在 Service Discovery 模式也是這樣。它提供服務自動生成與銷毀的生命週期管理,讓新的服務節點可以加入叢集,配合健康偵測只有自我檢查為健康的節點會被分配流量。
但是,這也意味著 Service Registry 必須保持高可用的狀態,否則整個系統將無法使用。所以,維護著 Service Registry 就是一筆額外的開銷,也因為透過 Service Discovery 的機制讓服務位址變成動態的,故確認系統問題將變得困難。
API Gateway 與 Service Discovery 的整合
- 當 API Gateway 收到一個請求時,它需要查詢 Service Registry,找到對應的服務實例,再進行轉發。
- 在 Kubernetes 環境下,通常會使用 K8s Service + Ingress Controller 來實現這個整合。
【範例】
- 使用者請求 /api/products/123
- API Gateway 收到請求,查詢 Service Registry 找到 Product Service 的實例
- Gateway 將請求轉發到對應的實例
- Product Service 返回資料給 Gateway,再返回給使用者
設計考量與實務建議
- API Gateway 建議事項
採用輕量化、事件驅動(如 Spring Cloud Gateway、Kong、NGINX、Envoy)。
整合安全控制(OAuth2, JWT)。
支援 API Composition,減少客戶端多次呼叫。
- Service Discovery 建議事項
小型專案可用 Server-side Discovery(例如 AWS ELB)。
大型多語言專案,建議採用 Client-side Discovery 搭配 Registry。
Kubernetes 環境下,直接使用內建的 Service + DNS + Ingress。
- 避免單點瓶頸
API Gateway、Service Registry 都必須是高可用架構(Cluster + 多副本)。
搭配健康檢查與熔斷器(Circuit Breaker)。
結語
- API Gateway:解決「如何對外提供統一入口」的問題。它不僅是反向代理,還能整合 API、進行安全控制、減少網路往返,甚至根據不同客戶端需求提供專屬 API。
- Service Discovery:解決「如何找到動態變化的服務實例」的問題。透過 Client-side Discovery 或 Server-side Discovery 搭配 Service Registry,系統能在彈性伸縮與動態環境中穩定運行。
兩者相輔相成:
- API Gateway 是門面,負責對外統一 API。
- Service Discovery 是電話簿,確保 Gateway 與服務之間能順利溝通。
在實際導入微服務時,這兩個模式幾乎是必備的基礎設施。