您好,登錄后才能下訂單哦!
微服務(wù)實戰(zhàn)中如何使用API Gateway,針對這個問題,這篇文章詳細介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
當(dāng)你決定將應(yīng)用作為一組微服務(wù)時,需要決定應(yīng)用客戶端如何與微服務(wù)交互。在單體式程序中,通常只有一組冗余的或者負載均衡的服務(wù)提供點。在微服務(wù)架構(gòu)中,每一個微服務(wù)暴露一組細粒度的服務(wù)提供點。我們來看它如何影響客戶端到服務(wù)端通信,同時提出一種API Gateway的方法。
假定你正在為在線購物應(yīng)用開發(fā)一個原生手機客戶端。你需要實現(xiàn)一個產(chǎn)品最終頁來展示商品信息。
例如,下面的圖展示了你在亞馬遜Android客戶端上滑動產(chǎn)品最終頁時看到的信息。
雖然這是一個智能手機應(yīng)用,這個產(chǎn)品最終頁展示了非常多的信息。例如,不僅這里有產(chǎn)品基本信息(名字、描述和價格),還有以下內(nèi)容:
購物車中的物品數(shù)
下單歷史
用戶評論
低庫存警告
快遞選項
各式各樣的推薦,包括經(jīng)常跟這個物品一起被購買的產(chǎn)品、購買該物品的其他顧客購買的產(chǎn)品以及購買該產(chǎn)品的顧客還瀏覽了哪些產(chǎn)品。
可選的購物選項
當(dāng)采用一個單體式應(yīng)用架構(gòu),一個移動客戶端將會通過一個REST請求(GET api.company.com/productdetails/productId)來獲取這些數(shù)據(jù)。一個負載均衡將請求分發(fā)到多個應(yīng)用實例之一。應(yīng)用將查詢各種數(shù)據(jù)庫并返回請求給客戶端。
相對的,若是采用微服務(wù)架構(gòu),最終頁上的數(shù)據(jù)會分布在不同的微服務(wù)上。下面列舉了可能與產(chǎn)品最終頁數(shù)據(jù)有關(guān)的一些微服務(wù):
購物車服務(wù) -- 購物車中的物品數(shù)
下單服務(wù) -- 下單歷史
分類服務(wù) -- 基本產(chǎn)品信息,如名字、圖片和價格
評論服務(wù) -- 用戶評論
庫存服務(wù) -- 低庫存警告
快遞服務(wù) -- 快遞選項、截止時間、來自不同快遞API的成本計算
推薦服務(wù) -- 推薦產(chǎn)品
我們需要決定移動客戶端如何訪問這些服務(wù)。請看下面這幾種方式
理論上說,一個客戶端可以直接給多個微服務(wù)中的任何一個發(fā)起請求。每一個微服務(wù)都會有一個對外服務(wù)端(https://serviceName.api.company.name)。這個URL可能會映射到微服務(wù)的負載均衡上,它再轉(zhuǎn)發(fā)請求到具體節(jié)點上。為了搜索產(chǎn)品細節(jié),移動端需要向上述微服務(wù)逐個發(fā)請求。
不幸的是,這個方案有很多困難和限制。其中一個問題是客戶端的需求量與每個微服務(wù)暴露的細粒度API數(shù)量的不匹配。如圖中,客戶端需要7次單獨請求。在更復(fù)雜的場景中,可能會需要更多次請求。例如,亞馬遜的產(chǎn)品最終頁要請求數(shù)百個微服務(wù)。雖然一個客戶端可以通過LAN發(fā)起很多個請求,但是在公網(wǎng)上這樣會很沒有效率,這個問題在移動互聯(lián)網(wǎng)上尤為突出。這個方案同時會導(dǎo)致客戶端代碼非常復(fù)雜。
另一個存在的問題是客戶端直接請求微服務(wù)的協(xié)議可能并不是web友好型。一個服務(wù)可能是用Thrift的RPC協(xié)議,而另一個服務(wù)可能是用AMQP消息協(xié)議。它們都不是瀏覽或防火墻友好的,并且最好是內(nèi)部使用。應(yīng)用應(yīng)該在防火墻外采用類似HTTP或者WEBSocket協(xié)議。
這個方案的另一個缺點是它很難重構(gòu)微服務(wù)。隨著時間的推移,我們可能需要改變系統(tǒng)微服務(wù)目前的切分方案。例如,我們可能需要將兩個服務(wù)合并或者將一個服務(wù)拆分為多個。但是,如果客戶端直接與微服務(wù)交互,那么這種重構(gòu)就很難實施。
由于上述三種問題的原因,客戶端直接與服務(wù)器端通信的方式很少在實際中使用。
通常來說,一個更好的解決辦法是采用API Gateway的方式。API Gateway是一個服務(wù)器,也可以說是進入系統(tǒng)的唯一節(jié)點。這跟面向?qū)ο笤O(shè)計模式中的Facade模式很像。API Gateway封裝內(nèi)部系統(tǒng)的架構(gòu),并且提供API給各個客戶端。它還可能有其他功能,如授權(quán)、監(jiān)控、負載均衡、緩存、請求分片和管理、靜態(tài)響應(yīng)處理等。下圖展示了一個適應(yīng)當(dāng)前架構(gòu)的API Gateway。
API Gateway負責(zé)請求轉(zhuǎn)發(fā)、合成和協(xié)議轉(zhuǎn)換。所有來自客戶端的請求都要先經(jīng)過API Gateway,然后路由這些請求到對應(yīng)的微服務(wù)。API Gateway將經(jīng)常通過調(diào)用多個微服務(wù)來處理一個請求以及聚合多個服務(wù)的結(jié)果。它可以在web協(xié)議與內(nèi)部使用的非Web友好型協(xié)議間進行轉(zhuǎn)換,如HTTP協(xié)議、WebSocket協(xié)議。
API Gateway可以提供給客戶端一個定制化的API。它暴露一個粗粒度API給移動客戶端。以產(chǎn)品最終頁這個使用場景為例。API Gateway提供一個服務(wù)提供點(/productdetails?productid=xxx)使得移動客戶端可以在一個請求中檢索到產(chǎn)品最終頁的全部數(shù)據(jù)。API Gateway通過調(diào)用多個服務(wù)來處理這一個請求并返回結(jié)果,涉及產(chǎn)品信息、推薦、評論等。
一個很好的API Gateway例子是Netfix API Gateway。Netflix流服務(wù)提供數(shù)百個不同的微服務(wù),包括電視、機頂盒、智能手機、游戲系統(tǒng)、平板電腦等。起初,Netflix視圖提供一個適用全場景的API。但是,他們發(fā)現(xiàn)這種形式不好用,因為涉及到各式各樣的設(shè)備以及它們獨特的需求?,F(xiàn)在,他們采用一個API Gateway來提供容錯性高的API,針對不同類型設(shè)備有相應(yīng)代碼。事實上,一個適配器處理一個請求平均要調(diào)用6到8個后端服務(wù)。Netflix API Gateway每天處理數(shù)十億的請求。
如你所料,采用API Gateway也是優(yōu)缺點并存的。API Gateway的一個最大好處是封裝應(yīng)用內(nèi)部結(jié)構(gòu)。相比起來調(diào)用指定的服務(wù),客戶端直接跟gatway交互更簡單點。API Gateway提供給每一個客戶端一個特定API,這樣減少了客戶端與服務(wù)器端的通信次數(shù),也簡化了客戶端代碼。
API Gateway也有一些缺點。它是一個高可用的組件,必須要開發(fā)、部署和管理。還有一個問題,它可能成為開發(fā)的一個瓶頸。開發(fā)者必須更新API Gateway來提供新服務(wù)提供點來支持新暴露的微服務(wù)。更新API Gateway時必須越輕量級越好。否則,開發(fā)者將因為更新Gateway而排隊列。但是,除了這些缺點,對于大部分的應(yīng)用,采用API Gateway的方式都是有效的。
既然我們已經(jīng)知道了采用API Gateway的動機和優(yōu)缺點,下面來看在設(shè)計它時需要考慮哪些事情。
只有少數(shù)公司需要處理像Netflix那樣的規(guī)模,每天需要處理數(shù)十億的請求。但是,對于大多數(shù)應(yīng)用,API Gateway的性能和可擴展性也是非常重要的。因此,創(chuàng)建一個支持同步、非阻塞I/O的API Gateway是有意義的。已經(jīng)有不同的技術(shù)可以用來實現(xiàn)一個可擴展的API Gateway。在JVM上,采用基于NIO技術(shù)的框架,如Netty,Vertx,Spring Reactor或者JBoss Undertow。Node.js是一個非JVM的流行平臺,它是一個在Chrome的JavaScript引擎基礎(chǔ)上建立的平臺。一個可選的方案是NGINX Plus。NGINX Plus提供一個成熟的、可擴展的、高性能web服務(wù)器和反向代理,它們均容易部署、配置和二次開發(fā)。NGINX Plus可以管理授權(quán)、權(quán)限控制、負載均衡、緩存并提供應(yīng)用健康檢查和監(jiān)控。
對于有些請求,API Gateway可以通過直接路由請求到對應(yīng)的后端服務(wù)上的方式來處理。對于另外一些請求,它需要調(diào)用多個后端服務(wù)并合并結(jié)果來處理。對于一些請求,例如產(chǎn)品最終頁面請求,發(fā)給后端服務(wù)的請求是相互獨立的。為了最小化響應(yīng)時間,API Gateway應(yīng)該并發(fā)的處理相互獨立的請求。但是,有時候請求之間是有依賴的。API Gateway可能需要先通過授權(quán)服務(wù)來驗證請求,然后在路由到后端服務(wù)。類似的,為了獲得客戶的產(chǎn)品愿望清單,需要先獲取該用戶的資料,然后返回清單上產(chǎn)品的信息。這樣的一個API 組件是Netflix Video Grid。
利用傳統(tǒng)的同步回調(diào)方法來實現(xiàn)API合并的代碼會使得你進入回調(diào)函數(shù)的噩夢中。這種代碼將非常難度且難以維護。一個優(yōu)雅的解決方案是采用反應(yīng)性編程模式來實現(xiàn)。類似的反應(yīng)抽象實現(xiàn)有Scala的Future,Java8的CompletableFuture和JavaScript的Promise。基于微軟.Net平臺的有Reactive Extensions(Rx)。Netflix為JVM環(huán)境創(chuàng)建了RxJava來使用他們的API Gateway。同樣地,JavaScript平臺有RxJS,可以在瀏覽器和Node.js平臺上運行。采用反應(yīng)編程方法可以幫助快速實現(xiàn)一個高效的API Gateway代碼。
一個基于微服務(wù)的應(yīng)用是一個分布式系統(tǒng),并且必須采用線程間通信的機制。有兩種線程間通信的方法。一種是采用異步機制,基于消息的方法。這類的實現(xiàn)方法有JMS和AMQP。另外的,例如Zeromq屬于服務(wù)間直接通信。還有一種線程間通信采用同步機制,例如Thrift和HTTP。事實上一個系統(tǒng)會同時采用同步和異步兩種機制。由于它的實現(xiàn)方式有很多種,因此API Gateway就需要支持多種通信方式。
API Gateway需要知道每一個微服務(wù)的IP和端口。在傳統(tǒng)應(yīng)用中,你可能會硬編碼這些地址,但是在現(xiàn)在云基礎(chǔ)的微服務(wù)應(yīng)用中,這將是個簡單的問題?;A(chǔ)服務(wù)通常會采用靜態(tài)地址,可以采用操作系統(tǒng)環(huán)境變量來指定。但是,探測應(yīng)用服務(wù)的地址就沒那么容易了。應(yīng)用服務(wù)通常動態(tài)分配地址和端口。同樣的,由于擴展或者升級,服務(wù)的實例也會動態(tài)的改變。因此,API Gateway需要采用系統(tǒng)的服務(wù)發(fā)現(xiàn)機制,要么采用服務(wù)端發(fā)現(xiàn),要么是客戶端發(fā)現(xiàn)。后續(xù)的一篇文章將會更詳細的介紹這部分。如果采用客戶端發(fā)現(xiàn)服務(wù),API Gateway必須要去查詢服務(wù)注冊處,也就是微服務(wù)實例地址的數(shù)據(jù)庫。
在實現(xiàn)API Gateway過程中,另外一個需要考慮的問題就是部分失敗。這個問題發(fā)生在分布式系統(tǒng)中當(dāng)一個服務(wù)調(diào)用另外一個服務(wù)超時或者不可用的情況。API Gateway不應(yīng)該被阻斷并處于無限期等待下游服務(wù)的狀態(tài)。但是,如何處理這種失敗依賴于特定的場景和具體服務(wù)。例如,如果是在產(chǎn)品詳情頁的推薦服務(wù)模塊無響應(yīng),那么API Gateway應(yīng)該返回剩下的其他信息給用戶,因為這些信息也是有用的。推薦部分可以返回空,也可以返回固定的頂部10個給用戶。但是,如果是產(chǎn)品信息服務(wù)無響應(yīng),那么API Gateway就應(yīng)該給客戶端返回一個錯誤。
在緩存有效的時候,API Gateway應(yīng)該能夠返回緩存。例如,由于產(chǎn)品價格變化并不頻繁,API Gateway在價格服務(wù)不可用時應(yīng)該返回緩存中的數(shù)值。這類數(shù)據(jù)可以由API Gateway自身來緩存,也可以由Redis或Memcached這類外部緩存實現(xiàn)。通過返回緩存數(shù)據(jù)或者默認數(shù)據(jù),API Gateway來確保系統(tǒng)錯誤不影響到用戶體驗。
Netflix Hystrix對于實現(xiàn)遠程服務(wù)調(diào)用代碼來說是一個非常好用的庫。Hystrix記錄那些超過預(yù)設(shè)定的極限值的調(diào)用。它實現(xiàn)了circuit break模式,使得可以將客戶端從無響應(yīng)服務(wù)的無盡等待中停止。如果一個服務(wù)的錯誤率超過預(yù)設(shè)值,Hystrix將中斷服務(wù),并且在一段時間內(nèi)所有請求立刻失效。Hystrix可以為請求失敗定義一個fallback操作,例如讀取緩存或者返回默認值。如果你在用JVM,就應(yīng)該考慮使用Hystrix。如果你采用的非JVM環(huán)境,那么應(yīng)該考慮采用類似功能的庫。
對于大多數(shù)微服務(wù)基礎(chǔ)的應(yīng)用,實現(xiàn)一個API Gateway都是有意義的,它就像是進入系統(tǒng)的一個服務(wù)提供點。API Gateway負責(zé)請求轉(zhuǎn)發(fā)、請求合成和協(xié)議轉(zhuǎn)換。它提供給應(yīng)用客戶端一個自定義的API。API Gateway可以通過返回緩存或者默認值的方式來掩蓋后端服務(wù)的錯誤。在
關(guān)于微服務(wù)實戰(zhàn)中如何使用API Gateway問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。