使用API網關構建微服務

本文總結

很是相似於API Manager提供的多租戶訂閱服務的功能。
 
將應用程序構建爲一組微服務時,須要肯定應用程序客戶端 如何與微服務交互。本文中,咱們將討論一下這對客戶端與應用程序之間的通訊有什麼影響,並提出一種使用API網關的方法。
 
當使用微服務架構時,產品詳情頁面顯示的數據歸多個微服務全部。
 

客戶端與微服務直接通訊

從理論上講,客戶端能夠直接向每一個微服務發送請求。每一個微服務都有一個公開的端點(https ://<serviceName>.api.company.name)。該URL將映射到微服務的負載均衡器,由它負責在可用實例之間分發請求。爲了獲取產品詳情,移動客戶端將逐一貫上面列出的N個服務發送請求。
 
遺憾的是,這種方法存在挑戰和侷限。一個問題是客戶端需求和每一個微服務暴露的細粒度API不匹配。在這個例子中,客戶端須要發送7個獨立請求。在更復雜的應用程序中,可能要發送更多的請求。例如,按照Amazon的說法,他們在顯示他們的產品頁面時就調用了數百個服務。然而,客戶端經過LAN發送許多請求,這在公網上可能會很低效,而在移動網絡上就根本不可行。這種方法還使得客戶端代碼很是複雜。
 
客戶端直接調用微服務的另外一個問題是,部分服務使用的協議不是Web友好協議。一個服務可能使用Thrift二進制RPC,而另外一個服務可能使用AMQP消息傳遞協議。無論哪一種協議都不是瀏覽器友好或防火牆友好的,最好是內部使用。在防火牆以外,應用程序應該使用諸如HTTP和WebSocket之類的協議。
 
這種方法的另外一個缺點是,它會使得微服務難以重構。隨着時間推移,咱們可能想要更改系統劃分紅服務的方式。例如,咱們可能合併兩個服務,或者將一個服務拆分紅兩個或更多服務。然而,若是客戶端與微服務直接通訊,那麼執行這類重構就很是困難了。
 
因爲這些問題的存在,客戶端與微服務直接通訊不多是合理的。
 

使用API網關

API網關是一個服務器,是系統的惟一入口。從面向對象設計的角度看,它與外觀模式相似。API網關封裝了系統內部架構,爲每一個客戶端提供一個定製的API。它可能還具備其它職責,如身份驗證、監控、負載均衡、緩存、「請求整形(request shaping)」與管理、靜態響應處理。
 
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網關有優勢也有不足。使用API網關的最大優勢是,它封裝了應用程序的內部結構。客戶端只須要同網關交互,而沒必要調用特定的服務。API網關爲每一類客戶端提供了特定的API。這減小了客戶端與應用程序間的交互次數,還簡化了客戶端代碼。
 
API網關也有一些不足。它增長了一個咱們必須開發、部署和維護的高可用組件。還有一個風險是,API網關變成了開發瓶頸。爲了暴露每一個微服務的端點,開發人員必須更新API網關。API網關的更新過程要儘量地簡單,這很重要。不然,爲了更新網關,開發人員將不得不排隊等待。不過,雖然有這些不足,但對於大多數現實世界的應用程序而言,使用API網關是合理的。
 

實現API網關

到目前爲止,咱們已經探討了使用API網關的動機及其優缺點。下面讓咱們看一下須要考慮的各類設計問題。
 
性能和可擴展性
 
只有少數公司有Netflix的規模,天天須要處理數十億請求。無論怎樣,對於大多數應用程序而言,API網關的性能和可擴展性一般都很是重要。所以,將API網關構建在一個支持異步、I/O非阻塞的平臺上是合理的。有多種不一樣的技術能夠用於實現一個可擴展的API網關。在JVM上,可使用一種基於NIO的框架,好比Netty、Vertx、Spring Reactor或JBoss Undertow中的一種。一個很是流行的非JVM選項是Node.js,它是一個以Chrome JavaScript引擎爲基礎構建的平臺。
 
另外一個選項是使用NGINX Plus。NGINX Plus提供了一個成熟的、可擴展的、高性能Web服務器和一個易於部署的、可配置可編程的反向代理。NGINX Plus能夠管理身份驗證、訪問控制、負載均衡請求、緩存響應,並提供應用程序可感知的健康檢查和監控。
 
使用響應式編程模型
 
API網關經過簡單地將請求路由給合適的後端服務來處理部分請求,而經過調用多個後端服務併合並結果來處理其它請求。對於部分請求,好比產品詳情相關的多個請求,它們對後端服務的請求是獨立於其它請求的。爲了最小化響應時間,API網關應該併發執行獨立請求。然而,有時候,請求之間存在依賴。在將請求路由到後端服務以前,API網關可能首先須要調用身份驗證服務驗證請求的合法性。相似地,爲了獲取客戶意願清單中的產品信息,API網關必須首先獲取包含那些信息的客戶資料,而後再獲取每一個產品的信息。關於API組合,另外一個有趣的例子是Netflix Video Grid。
 
使用傳統的異步回調方法編寫API組合代碼會讓你迅速墜入回調地獄。代碼會變得混亂、難以理解且容易出錯。一個更好的方法是使用響應式方法以一種聲明式樣式編寫API網關代碼。響應式抽象概念的例子有Scala中的Future、Java 8中的CompletableFuture和JavaScript中的Promise,還有最初是微軟爲.NET平臺開發的Reactive Extensions(RX)。Netflix建立了RxJava for JVM,專門用於他們的API網關。此外,還有RxJS for JavaScript,它既能夠在瀏覽器中運行,也能夠在Node.js中運行。使用響應式方法將使你能夠編寫簡單但高效的API網關代碼。
 
服務調用
 
基於微服務的應用程序是一個分佈式系統,必須使用一種進程間通訊機制。有兩種類型的進程間通訊機制可供選擇。一種是使用異步的、基於消息傳遞的機制。有些實現使用諸如JMS或AMQP那樣的消息代理,而其它的實現(如Zeromq)則沒有代理,服務間直接通訊。另外一種進程間通訊類型是諸如HTTP或Thrift那樣的同步機制。一般,一個系統會同時使用異步和同步兩種類型。它甚至還可能使用同一類型的多種實現。總之, API網關須要支持多種通訊機制
 
服務發現
 
API網關須要知道它與之通訊的每一個微服務的位置(IP地址和端口)。在傳統的應用程序中,或許能夠硬連線這個位置,但在現代的、基於雲的微服務應用程序中,這並非一個容易解決的問題。基礎設施服務(如消息代理)一般會有一個靜態位置,能夠經過OS環境變量指定。可是,肯定一個應用程序服務的位置沒有這麼簡單。應用程序服務的位置是動態分配的。並且,單個服務的一組實例也會隨着自動擴展或升級而動態變化。總之,像系統中的其它服務客戶端同樣,API網關須要使用系統的 服務發現機制,能夠是服務器端發現,也能夠是客戶端發現。下一篇文章將更詳細地描述服務發現。如今,須要注意的是,若是系統使用客戶端發現,那麼API網關必須可以 查詢服務註冊中心,這是一個包含全部 微服務實例及其位置的數據庫。
 
處理局部失敗
 
在實現API網關時,還有一個問題須要處理,就是局部失敗的問題。該問題在全部的分佈式系統中都會出現,不管何時,當一個服務調用另外一個響應慢或不可用的服務,就會出現這個問題。API網關永遠不能由於無限期地等待下游服務而阻塞。不過,如何處理失敗取決於特定的場景以及哪一個服務失敗。例如,在產品詳情場景下,若是推薦服務無響應,那麼API網關應該向客戶端返回產品詳情的其它內容,由於它們對用戶依然有用。推薦內容能夠爲空,也能夠,好比說,用一個固定的TOP 10列表取代。不過,若是產品信息服務無響應,那麼API網關應該 向客戶端返回一個錯誤信息
 
若是緩存數據可用,那麼API網關還能夠返回緩存數據。例如,因爲產品價格不常常變化,因此若是價格服務不可用,API網關能夠返回緩存的價格數據。數據能夠由API網關本身緩存,也能夠存儲在像Redis或Memcached那樣的外部緩存中。經過返回默認數據或者緩存數據,API網關能夠確保系統故障不影響用戶的體驗。
 
在編寫代碼調用遠程服務方面,Netflix Hystrix是一個異常有用的庫。Hystrix會將超出設定閥值的調用超時。它實現了一個「斷路器(circuit breaker)」模式,能夠防止客戶端對無響應的服務進行沒必要要的等待。若是服務的錯誤率超出了設定的閥值,那麼Hystrix會切斷斷路器,在一個指定的時間範圍內,全部請求都會當即失敗。Hystrix容許用戶定義一個請求失敗後的後援操做,好比從緩存讀取數據,或者返回一個默認值。若是你正在使用JVM,那麼你絕對應該考慮使用Hystrix。而若是你正在使用一個非JVM環境,那麼你應該使用一個等效的庫。
 
小結
 
對於大多數基於微服務的應用程序而言,實現一個API網關是有意義的,它能夠做爲 系統的惟一入口
API網關負責 服務請求路由、組合及協議轉換。它爲每一個應用程序客戶端提供一個定製的API。API網關還能夠經過返回緩存數據或默認數據 屏蔽後端服務失敗。在本系列的下一篇文章中,咱們將探討服務間通訊。

網址

相關文章
相關標籤/搜索