引言
API Gateway負(fù)責(zé)請求轉(zhuǎn)發(fā)、合成和協(xié)議轉(zhuǎn)換。所有來自客戶端的請求都要先經(jīng)過API Gateway,然后路由這些請求到對應(yīng)的微服務(wù)灭返。API Gateway將經(jīng)常通過調(diào)用多個(gè)微服務(wù)來處理一個(gè)請求以及聚合多個(gè)服務(wù)的結(jié)果。它可以在web協(xié)議與內(nèi)部使用的非Web友好型協(xié)議間進(jìn)行轉(zhuǎn)換坤邪,如HTTP協(xié)議熙含、WebSocket協(xié)議。
簡述
API Gateway
API Gateway可以提供給客戶端一個(gè)定制化的API艇纺。它暴露一個(gè)粗粒度API給移動客戶端婆芦。以產(chǎn)品最終頁這個(gè)使用場景為例。API Gateway提供一個(gè)端點(diǎn)(/productdetails?productid=xxx)使得移動客戶端可以在一個(gè)請求中檢索到產(chǎn)品最終頁的全部數(shù)據(jù)喂饥。API Gateway通過調(diào)用多個(gè)服務(wù)來處理這一個(gè)請求并返回結(jié)果,涉及產(chǎn)品信息肠鲫、推薦员帮、評論等。
一個(gè)很好的API Gateway例子是 Netfix API Gateway 导饲。Netflix流服務(wù)提供數(shù)百個(gè)不同的微服務(wù)捞高,包括電視、機(jī)頂盒渣锦、智能手機(jī)硝岗、游戲系統(tǒng)、平板電腦等袋毙。起初型檀,Netflix視圖提供一個(gè) 適用全場景 的API。但是听盖,他們發(fā)現(xiàn)這種形式不好用胀溺,因?yàn)樯婕暗礁魇礁鳂拥脑O(shè)備以及它們獨(dú)特的需求。現(xiàn)在皆看,他們采用一個(gè)API Gateway來提供容錯(cuò)性高的API仓坞,針對不同類型設(shè)備有相應(yīng)代碼。事實(shí)上腰吟,一個(gè)適配器處理一個(gè)請求平均要調(diào)用6到8個(gè)后端服務(wù)无埃。Netflix API Gateway每天處理數(shù)十億的請求。
實(shí)現(xiàn)一個(gè)API Gateway
既然我們已經(jīng)知道了采用API Gateway的動機(jī)和優(yōu)缺點(diǎn),下面來看在設(shè)計(jì)它時(shí)需要考慮哪些事情嫉称。
性能和可擴(kuò)展性
只有少數(shù)公司需要處理像Netflix那樣的規(guī)模侦镇,每天需要處理數(shù)十億的請求。但是澎埠,對于大多數(shù)應(yīng)用虽缕,API Gateway的性能和可擴(kuò)展性也是非常重要的。因此蒲稳,創(chuàng)建一個(gè)支持同步氮趋、非阻塞I/O的API Gateway是有意義的。已經(jīng)有不同的技術(shù)可以用來實(shí)現(xiàn)一個(gè)可擴(kuò)展的API Gateway江耀。在JVM上剩胁,采用基于NIO技術(shù)的框架,如Netty祥国,Vertx昵观,Spring Reactor或者JBoss Undertow。Node.js是一個(gè)非JVM的流行平臺舌稀,它是一個(gè)在Chrome的JavaScript引擎基礎(chǔ)上建立的平臺啊犬。一個(gè)可選的方案是NGINX Plus。NGINX Plus提供一個(gè)成熟的壁查、可擴(kuò)展的觉至、高性能web服務(wù)器和反向代理,它們均容易部署睡腿、配置和二次開發(fā)语御。NGINX Plus可以管理授權(quán)、權(quán)限控制席怪、負(fù)載均衡应闯、緩存并提供應(yīng)用健康檢查和監(jiān)控。
采用反應(yīng)性編程模型
對于有些請求挂捻,API Gateway可以通過直接路由請求到對應(yīng)的后端服務(wù)上的方式來處理碉纺。對于另外一些請求,它需要調(diào)用多個(gè)后端服務(wù)并合并結(jié)果來處理刻撒。對于一些請求惜辑,例如產(chǎn)品最終頁面請求,發(fā)給后端服務(wù)的請求是相互獨(dú)立的疫赎。為了最小化響應(yīng)時(shí)間盛撑,API Gateway應(yīng)該并發(fā)的處理相互獨(dú)立的請求。但是捧搞,有時(shí)候請求之間是有依賴的抵卫。API Gateway可能需要先通過授權(quán)服務(wù)來驗(yàn)證請求狮荔,然后在路由到后端服務(wù)。類似的介粘,為了獲得客戶的產(chǎn)品愿望清單殖氏,需要先獲取該用戶的資料,然后返回清單上產(chǎn)品的信息姻采。這樣的一個(gè)API 組件是Netflix Video Grid雅采。
利用傳統(tǒng)的同步回調(diào)方法來實(shí)現(xiàn)API合并的代碼會使得你進(jìn)入回調(diào)函數(shù)的噩夢中。這種代碼將非常難度且難以維護(hù)慨亲。一個(gè)優(yōu)雅的解決方案是采用反應(yīng)性編程模式來實(shí)現(xiàn)婚瓜。類似的反應(yīng)抽象實(shí)現(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ùn)行碍舍。采用反應(yīng)編程方法可以幫助快速實(shí)現(xiàn)一個(gè)高效的API Gateway代碼柠座。
服務(wù)調(diào)用
一個(gè)基于微服務(wù)的應(yīng)用是一個(gè)分布式系統(tǒng),并且必須采用線程間通信的機(jī)制片橡。有兩種線程間通信的方法妈经。一種是采用同步機(jī)制,基于消息的方法锻全。這類的實(shí)現(xiàn)方法有JMS和AMQP。另外的录煤,例如Zeromq屬于服務(wù)間直接通信鳄厌。還有一種線程間通信采用異步機(jī)制,例如Thrift和HTTP妈踊。事實(shí)上一個(gè)系統(tǒng)會同時(shí)采用同步和異步兩種機(jī)制了嚎。由于它的實(shí)現(xiàn)方式有很多種,因此API Gateway就需要支持多種通信方式廊营。
服務(wù)發(fā)現(xiàn)
API Gateway需要知道每一個(gè)微服務(wù)的IP和端口歪泳。在傳統(tǒng)應(yīng)用中,你可能會硬編碼這些地址露筒,但是在現(xiàn)在云基礎(chǔ)的微服務(wù)應(yīng)用中呐伞,這將是個(gè)簡單的問題∩魇剑基礎(chǔ)服務(wù)通常會采用靜態(tài)地址伶氢,可以采用操作系統(tǒng)環(huán)境變量來指定趟径。但是,探測應(yīng)用服務(wù)的地址就沒那么容易了癣防。應(yīng)用服務(wù)通常動態(tài)分配地址和端口蜗巧。同樣的,由于擴(kuò)展或者升級蕾盯,服務(wù)的實(shí)例也會動態(tài)的改變幕屹。因此,API Gateway需要采用系統(tǒng)的服務(wù)發(fā)現(xiàn)機(jī)制级遭,要么采用服務(wù)端發(fā)現(xiàn)望拖,要么是客戶端發(fā)現(xiàn)。后續(xù)的一篇文章將會更詳細(xì)的介紹這部分装畅。如果采用客戶端發(fā)現(xiàn)服務(wù)靠娱,API Gateway必須要去查詢服務(wù)注冊處,也就是微服務(wù)實(shí)例地址的數(shù)據(jù)庫掠兄。
處理部分失敗
在實(shí)現(xiàn)API Gateway過程中像云,另外一個(gè)需要考慮的問題就是部分失敗。這個(gè)問題發(fā)生在分布式系統(tǒng)中當(dāng)一個(gè)服務(wù)調(diào)用另外一個(gè)服務(wù)超時(shí)或者不可用的情況蚂夕。API Gateway不應(yīng)該被阻斷并處于無限期等待下游服務(wù)的狀態(tài)迅诬。但是,如何處理這種失敗依賴于特定的場景和具體服務(wù)婿牍。例如侈贷,如果是在產(chǎn)品詳情頁的推薦服務(wù)模塊無響應(yīng),那么API Gateway應(yīng)該返回剩下的其他信息給用戶等脂,因?yàn)檫@些信息也是有用的俏蛮。推薦部分可以返回空,也可以返回固定的頂部10個(gè)給用戶上遥。但是搏屑,如果是產(chǎn)品信息服務(wù)無響應(yīng),那么API Gateway就應(yīng)該給客戶端返回一個(gè)錯(cuò)誤粉楚。
在緩存有效的時(shí)候辣恋,API Gateway應(yīng)該能夠返回緩存。例如模软,由于產(chǎn)品價(jià)格變化并不頻繁伟骨,API Gateway在價(jià)格服務(wù)不可用時(shí)應(yīng)該返回緩存中的數(shù)值。這類數(shù)據(jù)可以由API Gateway自身來緩存燃异,也可以由Redis或Memcached這類外部緩存實(shí)現(xiàn)携狭。通過返回緩存數(shù)據(jù)或者默認(rèn)數(shù)據(jù),API Gateway來確保系統(tǒng)錯(cuò)誤不影響到用戶體驗(yàn)回俐。
Netflix Hystrix對于實(shí)現(xiàn)遠(yuǎn)程服務(wù)調(diào)用代碼來說是一個(gè)非常好用的庫暑中。Hystrix記錄那些超過預(yù)設(shè)定的極限值的調(diào)用壹瘟。它實(shí)現(xiàn)了circuit break模式,使得可以將客戶端從無響應(yīng)服務(wù)的無盡等待中停止鳄逾。如果一個(gè)服務(wù)的錯(cuò)誤率超過預(yù)設(shè)值稻轨,Hystrix將中斷服務(wù),并且在一段時(shí)間內(nèi)所有請求立刻失效雕凹。Hystrix可以為請求失敗定義一個(gè)fallback操作殴俱,例如讀取緩存或者返回默認(rèn)值。如果你在用JVM枚抵,就應(yīng)該考慮使用Hystrix线欲。如果你采用的非JVM環(huán)境,那么應(yīng)該考慮采用類似功能的庫汽摹。
總結(jié)
以 上就是我對Java開發(fā)大型互聯(lián)網(wǎng)微服務(wù)構(gòu)建-實(shí)現(xiàn)一個(gè)API Gateway服務(wù)器問題及其優(yōu)化總結(jié)李丰,分享給大家,覺得收獲的話可以點(diǎn)個(gè)關(guān)注收藏轉(zhuǎn)發(fā)一波喔逼泣,謝謝大佬們支持趴泌!
最后,每一位讀到這里的網(wǎng)友拉庶,感謝你們能耐心地看完嗜憔。希望在成為一名更優(yōu)秀的Java程序員的道路上,我們可以一起學(xué)習(xí)氏仗、一起進(jìn)步吉捶!都能贏取白富美,走向架構(gòu)師的人生巔峰!
想了解學(xué)習(xí)Java方面的技術(shù)內(nèi)容以及Java技術(shù)視頻的內(nèi)容可加群:815220368皆尔,歡迎大家的加入喲呐舔!