Chris Richardson微服務翻譯:構建微服務之使用API網關

Chris Richardson 微服務系列翻譯全7篇連接:html

原文連接:Building Microservices: Using an API Gateway
java


介紹

假設咱們爲一個商品應用開發一個移動APP,咱們應該提供一個產品詳情頁來展現指定產品的信息。Amazon Android 應用在商品詳情頁展現的內容,以下圖所示:react

儘管只是移動APP,商品詳情頁依然展現給咱們不少信息,不只包括基本信息(名稱、描述、價格),還包含以下內容:nginx

  • 購物車中的商品數
  • 歷史訂單記錄
  • 買家評價
  • 低庫存預警
  • 送貨選項
  • 推薦:包括與此商品一塊兒購買的其餘商品、購買該商品的顧客還買的其餘商品、購買該商品的顧客還看過其餘的商品
  • 其餘購物選項

使用單體應用架構時,移動APP經過單一的 REST 請求(GET api.company.com/productdetails/productId)來獲取展現的數據。負載均衡會將請求路由到多個相同實例的其中一個,而後程序查詢各類數據庫表,返回數據給客戶端。git

對應若是採用微服務架構,展現在產品詳情頁的數據會來自不一樣的微服務上。下面列舉一些微服務對應的展現數據:github

  • 購物車服務:購物車中的商品數
  • 訂單服務:訂單記錄
  • 目錄服務:商品基本信息,如名稱、圖片和價格
  • 評論服務:用戶評價
  • 庫存服務:低庫存預警
  • 配送服務:送貨選項、期限和費用
  • 推薦服務:推薦商品

客戶端如何訪問這些服務,讓咱們看看下面的方法。web

客戶端與服務端直接通訊

理論上客戶端能夠直接請求每一個微服務,每一個微服務都有一個公開的節點(https://serviceName.api.company.com),該 URL 映射到負載均衡,而後被分發到可用的實例上處理,爲了獲取產品詳情,移動客戶端須要向上述每一個服務發送請求。數據庫

遺憾的是,這種方法存在挑戰和侷限:編程

1)客戶端需求和每一個微服務暴露出的細粒度 API 不匹配。本例中客戶端須要發送7個不一樣的請求,在一個複雜的應用中請求數甚至還要更多,例如亞馬遜在顯示他們的產品頁面時會調用數百個服務。這種方法還使得客戶端代碼很是複雜。後端

2)一些服務使用的協議對 web 並不友好。一個服務可能使用 Thrift 的二進制 RPC,而另外一個服務可能使用 AMQP 消息協議。這些協議不是瀏覽器和防火牆友好的,最好在內部使用。而防火牆以外,應用程序最好使用 HTTP 或 WebSocket 之類的協議。

3)這種方法會使得微服務難以重構。隨着時間的推移,咱們可能要從新規劃、合併或拆分微服務,若是客戶端直接與微服務通訊的話,對這些微服務進行重構變得異常困難。

正是這些緣由,採用客戶端直接調用微服務的方式並不明智。

使用 API 網關

一般更好的方式是使用 API 網關,API 網關是提供系統惟一入口的服務器,他和設計模式中的 外觀模式 相似:API 網關封裝內部系統架構,並向客戶端提供 API。它還可能負責諸如 用戶驗證、監控、負載均衡、緩存、請求管理、靜態響應處理等功能。下圖展現了適應 API 網關的架構:

API 網關負責請求路由、組合和協議轉換。來自客戶端的全部請求都先通過 API 網關,而後被路由到對應的微服務中,API 網關一般調用多個微服務並聚合其結果來處理請求。它能夠在 web 協議(如 HTTP 和 WebSocket)與內部使用的非 web 協議之間轉換。

API 網關能夠爲每一個客戶端提供定製的 API,它一般爲移動客戶端暴露粗粒度的 API。例如:商品詳情頁,API 網關提供 (/productdetails?productid=xxx) 節點使得移動客戶端單一請求能夠獲取全部的產品明細。API 網關調用各個服務(商品信息、推薦、評論等)合併結果並返回。

Netflix API網關 就是一個很好的 API 網關實例。Netflix 流媒體服務提供給成百上千的設備使用,包括電視、機頂盒、智能手機、遊戲系統、平板電腦等。最初,Netflix 視圖爲他們的流服務提供通用的 API,然而,他們發現因爲設備的獨特需求,這種設計方式不能很好的工做。現在他們使用 API 網關經過運行設備的適配器代碼爲客戶端提供定製的 API,一般適配器爲每一個請求平均調用6~7個微服務,Netflix API網關天天處理數十億請求。

使用 API 網關的優點及劣勢

使用 API 網關有優點也有不足。

最大優勢是:
1)它封裝了應用的內部結構,客戶端只須要簡單的與 API 網關交互便可,而不用直接調用每一個服務。
2)API 網關爲不一樣的客戶端提供定製的 API,減小了客戶端和應用間的交互次數,並大大簡化了客戶端的代碼。

API 網關也有其不足:
1)它自己增長了一個須要開發、部署和維護的高可用組件。
2)API 網關有時候變成了開發的瓶頸。開發者爲了暴露新的微服務必須更新 API 網關。API 網關的更新流程要儘量的簡單,不然,開發人員不得不排隊等待。儘管它有這些不足,但對於大部分的應用程序而言,使用 API 網關是合理的。

實現一個 API 網關

目前咱們討論了 API 網關的動機和一些優缺點。下面咱們看一些須要考慮的一些設計問題。

性能與擴展性

只有少數公司擁有 Netflix 這樣的規模,天天須要處理數十億的請求。對於大多數程序而言,API 網關的性能和可擴展性是很是重要的。所以,API 網關構建在一個支持異步、IO 非阻塞的平臺上是合理的。有多種不一樣的技術可參考:JVM 上,基於 NIO 的框架,好比 Netty、Vertx、 Spring Reactor 或 JBoss Undertow 等。一個流行的選項是 Node.js,他是構建於 Chrome JS 引擎的平臺。另外一個選項是 NGINX Plus,他提供了成熟、可擴展、高性能的 web 服務器和一個易於部署的、可配置可編程的反向代理。NGINX Plus 能夠管理身份驗證、權限控制、負載均衡、緩存以及應用級別的健康檢查及監控。

使用響應式編程模型

API 網關將請求路由到相應的多個微服務併合並處理結果,對於一些請求,例如產品詳情頁,後端對應的服務是彼此獨立的,爲了減小響應時間,API 網關應並行處理這些請求。然而有時候,請求之間是有依賴關係的,在請求微服務以前,API 網關須要調用身份驗證服務來驗證請求的合法性。相似的,獲取用戶心願單上的產品信息時,API 網關須要先獲取包含這些信息的客戶資料,而後再去獲取信息的詳情。另外一個有趣的例子就是:Netflix Video Grid

使用傳統的異步回調方式來寫 API 組合代碼會把你帶入地獄。代碼會變的混亂、難以理解且容易出錯。更好的方式是使用響應式方法,以一種聲明式樣式編寫 API 網關代碼。例如:Scala中的 Future 、Java 8中的 CompletableFuture 以及JavaScript中的 Promise,還有微軟爲.NET開發的 Reactive Extensions。Netflix 爲他們的 API 網關建立了 RxJava for JVM,此外還有 RxJS for JavaScript,既能夠在瀏覽器中運行,也能夠在Node.js 中運行。響應式風格將幫助你寫出簡潔高效的 API 網關代碼。

服務調用

微服務架構是一個進程間通訊的分佈式系統, 有兩種進程間通訊方式:一種是採用異步、基於消息傳遞的機制。例如:JMS 或 AMQP 這樣的消息組件;另外一種是使用 HTTP 或 Thrfit 這種同步機制進行通訊。一般,一個系統會同時使用同步和異步方式,甚至還會使用同一類型的多種實現。總之,API 網關須要支持不一樣的通訊機制。

服務發現

API 網關須要知道和他通訊的每一個微服務的地址(IP和端口號)。傳統應用中,可使用硬編碼的方式,可是在現代基於雲的微服務應用中,這不是一個容易解決的問題。基礎架構服務(例如:消息組件)一般會有一個靜態地址,能夠在環境變量中指定。然而,獲取一個微服務地址就不是簡單的事了,微服務的地址是動態分配的,一組服務實例可能由於自動擴展或升級而動態的變化。所以 API 網關須要服務發現機制,能夠是服務器端發現,或者是客戶端發現(後面的文章會詳細介紹服務發現的問題)。若是使用客戶端發現的話,API 網關應該能查詢服務註冊中心,這是一個包含全部微服務實例及其地址的數據庫。

處理局部故障

局部故障在分佈式系統中很常見,當一個服務調用另外一個服務,當後者響應慢或不可用時就出現了這個問題。API 網關不能由於無限期的等待下游服務而阻塞。不過,如何處理失敗取決於應用場景或具體哪一個服務失敗,例如:產品詳情頁,推薦服務掛了,那麼 API 網關應該返回其餘產品信息,保障產品對用戶仍然可用,推薦內容可爲空或使用固定的 Top 10 列表取代。不過,若是產品服務掛了,那麼 API 網關應該返回客戶端錯誤信息。

API 網關也能夠緩存返回的數據。例如:產品價格變更不頻繁,當價格服務不可用時,API 網關能夠返回緩存的價格數據。數據能夠是 API 網關本身緩存,也可使用 Redis 或 Memcached之類的外部緩存。經過返回默認值或緩存值,API 網關保證局部故障不會影響用戶體驗。

Netflix Hystrix 在編寫代碼調用遠程服務時是很是有用的,Hystrix 會標記超過特定閥值的調用爲超時,他還實現了『熔斷器』模式來防止對無響應服務的更多請求,若是一個服務的出錯率超過了特定閥值,那麼 Hystrix 會觸發熔斷器,全部請求會快速失敗並持續一段時間。Hystrix 容許用戶定義請求失敗時的 fallback 操做,例如:讀取緩存或返回默認值。若是你在使用 JVM ,那麼應該考慮使用 Hystrix,若是使用的是非 JVM 環境,那麼可使用一個功能相同的庫。

總結

對於大部分基於微服務的應用,實現 API 網關做爲應用的單一入口是明智的。API 網關負責請求路由、聚合、協議轉換。爲每一個客戶端提供特定的 API,還能夠經過返回默認值或緩存值來處理後端服務的調用失敗。下篇文章,咱們將討論服務間的通訊。

相關文章
相關標籤/搜索