微服務實戰(二):使用API Gateway

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。

當你決定將應用作為一組微服務時,需要決定應用客戶端如何與微服務交互。在單體式程序中,通常只有一組冗余的或者負載均衡的服務提供點。在微服務架構中,每一個微服務暴露一組細粒度的服務提供點。在本篇文章中,我們來看它如何影響客戶端到服務端通信,同時提出一種API Gateway的方法。

介紹

假定你正在為在線購物應用開發一個原生手機客戶端。你需要實現一個產品最終頁來展示商品信息。

例如,下面的圖展示了你在亞馬遜Android客戶端上滑動產品最終頁時看到的信息。

01.png


雖然這是一個智能手機應用,這個產品最終頁展示了非常多的信息。例如,不僅這里有產品基本信息(名字、描述和價格),還有以下內容:

?

?

  • 購物車中的物品數
  • 下單歷史
  • 用戶評論
  • 低庫存警告
  • 快遞選項
  • 各式各樣的推薦,包括經常跟這個物品一起被購買的產品、購買該物品的其他顧客購買的產品以及購買該產品的顧客還瀏覽了哪些產品。
  • 可選的購物選項


當采用一個單體式應用架構,一個移動客戶端將會通過一個REST請求(GET api.company.com/productdetails/productId)來獲取這些數據。一個負載均衡將請求分發到多個應用實例之一。應用將查詢各種數據庫并返回請求給客戶端。

相對的,若是采用微服務架構,最終頁上的數據會分布在不同的微服務上。下面列舉了可能與產品最終頁數據有關的一些微服務:

?

?

  • 購物車服務 -- 購物車中的物品數
  • 下單服務 -- 下單歷史
  • 分類服務 -- 基本產品信息,如名字、圖片和價格
  • 評論服務 -- 用戶評論
  • 庫存服務 -- 低庫存警告
  • 快遞服務 -- 快遞選項、截止時間、來自不同快遞API的成本計算
  • 推薦服務 -- 推薦產品

?

02.png


我們需要決定移動客戶端如何訪問這些服務。請看下面這幾種方式

?

?

客戶端到微服務直接通信

理論上說,一個客戶端可以直接給多個微服務中的任何一個發起請求。每一個微服務都會有一個對外服務端(https://serviceName.api.company.name)。這個URL可能會映射到微服務的負載均衡上,它再轉發請求到具體節點上。為了搜索產品細節,移動端需要向上述微服務逐個發請求。

不幸的是,這個方案有很多困難和限制。其中一個問題是客戶端的需求量與每個微服務暴露的細粒度API數量的不匹配。如圖中,客戶端需要7次單獨請求。在更復雜的場景中,可能會需要更多次請求。例如,亞馬遜的產品最終頁要請求數百個微服務。雖然一個客戶端可以通過LAN發起很多個請求,但是在公網上這樣會很沒有效率,這個問題在移動互聯網上尤為突出。這個方案同時會導致客戶端代碼非常復雜。

另一個存在的問題是客戶端直接請求微服務的協議可能并不是web友好型。一個服務可能是用Thrift的RPC協議,而另一個服務可能是用AMQP消息協議。它們都不是瀏覽或防火墻友好的,并且最好是內部使用。應用應該在防火墻外采用類似HTTP或者WEBSocket協議。

這個方案的另一個缺點是它很難重構微服務。隨著時間的推移,我們可能需要改變系統微服務目前的切分方案。例如,我們可能需要將兩個服務合并或者將一個服務拆分為多個。但是,如果客戶端直接與微服務交互,那么這種重構就很難實施。

由于上述三種問題的原因,客戶端直接與服務器端通信的方式很少在實際中使用。

?

?

采用一個API Gateway

通常來說,一個更好的解決辦法是采用API Gateway的方式。API Gateway是一個服務器,也可以說是進入系統的唯一節點。這跟面向對象設計模式中的Facade模式很像。API Gateway封裝內部系統的架構,并且提供API給各個客戶端。它還可能有其他功能,如授權、監控、負載均衡、緩存、請求分片和管理、靜態響應處理等。下圖展示了一個適應當前架構的API Gateway。

?

03.png


API Gateway負責請求轉發、合成和協議轉換。所有來自客戶端的請求都要先經過API Gateway,然后路由這些請求到對應的微服務。API Gateway將經常通過調用多個微服務來處理一個請求以及聚合多個服務的結果。它可以在web協議與內部使用的非Web友好型協議間進行轉換,如HTTP協議、WebSocket協議。

API Gateway可以提供給客戶端一個定制化的API。它暴露一個粗粒度API給移動客戶端。以產品最終頁這個使用場景為例。API Gateway提供一個服務提供點(/productdetails?productid=xxx)使得移動客戶端可以在一個請求中檢索到產品最終頁的全部數據。API Gateway通過調用多個服務來處理這一個請求并返回結果,涉及產品信息、推薦、評論等。

一個很好的API Gateway例子是Netfix API Gateway。Netflix流服務提供數百個不同的微服務,包括電視、機頂盒、智能手機、游戲系統、平板電腦等。起初,Netflix視圖提供一個適用全場景的API。但是,他們發現這種形式不好用,因為涉及到各式各樣的設備以及它們獨特的需求。現在,他們采用一個API Gateway來提供容錯性高的API,針對不同類型設備有相應代碼。事實上,一個適配器處理一個請求平均要調用6到8個后端服務。Netflix API Gateway每天處理數十億的請求。

?

?

API Gateway的優點和缺點

如你所料,采用API Gateway也是優缺點并存的。API Gateway的一個最大好處是封裝應用內部結構。相比起來調用指定的服務,客戶端直接跟gatway交互更簡單點。API Gateway提供給每一個客戶端一個特定API,這樣減少了客戶端與服務器端的通信次數,也簡化了客戶端代碼。

API Gateway也有一些缺點。它是一個高可用的組件,必須要開發、部署和管理。還有一個問題,它可能成為開發的一個瓶頸。開發者必須更新API Gateway來提供新服務提供點來支持新暴露的微服務。更新API Gateway時必須越輕量級越好。否則,開發者將因為更新Gateway而排隊列。但是,除了這些缺點,對于大部分的應用,采用API Gateway的方式都是有效的。

?

?

實現一個API Gateway

既然我們已經知道了采用API Gateway的動機和優缺點,下面來看在設計它時需要考慮哪些事情。

?

?

性能和可擴展性

只有少數公司需要處理像Netflix那樣的規模,每天需要處理數十億的請求。但是,對于大多數應用,API Gateway的性能和可擴展性也是非常重要的。因此,創建一個支持同步、非阻塞I/O的API Gateway是有意義的。已經有不同的技術可以用來實現一個可擴展的API Gateway。在JVM上,采用基于NIO技術的框架,如Netty,Vertx,Spring Reactor或者JBoss Undertow。Node.js是一個非JVM的流行平臺,它是一個在Chrome的JavaScript引擎基礎上建立的平臺。一個可選的方案是NGINX Plus。NGINX Plus提供一個成熟的、可擴展的、高性能web服務器和反向代理,它們均容易部署、配置和二次開發。NGINX Plus可以管理授權、權限控制、負載均衡、緩存并提供應用健康檢查和監控。

?

采用反應性編程模型

對于有些請求,API Gateway可以通過直接路由請求到對應的后端服務上的方式來處理。對于另外一些請求,它需要調用多個后端服務并合并結果來處理。對于一些請求,例如產品最終頁面請求,發給后端服務的請求是相互獨立的。為了最小化響應時間,API Gateway應該并發的處理相互獨立的請求。但是,有時候請求之間是有依賴的。API Gateway可能需要先通過授權服務來驗證請求,然后在路由到后端服務。類似的,為了獲得客戶的產品愿望清單,需要先獲取該用戶的資料,然后返回清單上產品的信息。這樣的一個API 組件是Netflix Video Grid

利用傳統的同步回調方法來實現API合并的代碼會使得你進入回調函數的噩夢中。這種代碼將非常難度且難以維護。一個優雅的解決方案是采用反應性編程模式來實現。類似的反應抽象實現有Scala的Future,Java8的CompletableFuture和JavaScript的Promise。基于微軟.Net平臺的有Reactive Extensions(Rx)。Netflix為JVM環境創建了RxJava來使用他們的API Gateway。同樣地,JavaScript平臺有RxJS,可以在瀏覽器和Node.js平臺上運行。采用反應編程方法可以幫助快速實現一個高效的API Gateway代碼。

?

服務調用

一個基于微服務的應用是一個分布式系統,并且必須采用線程間通信的機制。有兩種線程間通信的方法。一種是采用異步機制,基于消息的方法。這類的實現方法有JMS和AMQP。另外的,例如Zeromq屬于服務間直接通信。還有一種線程間通信采用同步機制,例如Thrift和HTTP。事實上一個系統會同時采用同步和異步兩種機制。由于它的實現方式有很多種,因此API Gateway就需要支持多種通信方式。

?

服務發現

API Gateway需要知道每一個微服務的IP和端口。在傳統應用中,你可能會硬編碼這些地址,但是在現在云基礎的微服務應用中,這將是個簡單的問題。基礎服務通常會采用靜態地址,可以采用操作系統環境變量來指定。但是,探測應用服務的地址就沒那么容易了。應用服務通常動態分配地址和端口。同樣的,由于擴展或者升級,服務的實例也會動態的改變。因此,API Gateway需要采用系統的服務發現機制,要么采用服務端發現,要么是客戶端發現。后續的一篇文章將會更詳細的介紹這部分。如果采用客戶端發現服務,API Gateway必須要去查詢服務注冊處,也就是微服務實例地址的數據庫。

?

處理部分失敗

在實現API Gateway過程中,另外一個需要考慮的問題就是部分失敗。這個問題發生在分布式系統中當一個服務調用另外一個服務超時或者不可用的情況。API Gateway不應該被阻斷并處于無限期等待下游服務的狀態。但是,如何處理這種失敗依賴于特定的場景和具體服務。例如,如果是在產品詳情頁的推薦服務模塊無響應,那么API Gateway應該返回剩下的其他信息給用戶,因為這些信息也是有用的。推薦部分可以返回空,也可以返回固定的頂部10個給用戶。但是,如果是產品信息服務無響應,那么API Gateway就應該給客戶端返回一個錯誤。

在緩存有效的時候,API Gateway應該能夠返回緩存。例如,由于產品價格變化并不頻繁,API Gateway在價格服務不可用時應該返回緩存中的數值。這類數據可以由API Gateway自身來緩存,也可以由Redis或Memcached這類外部緩存實現。通過返回緩存數據或者默認數據,API Gateway來確保系統錯誤不影響到用戶體驗。

Netflix Hystrix對于實現遠程服務調用代碼來說是一個非常好用的庫。Hystrix記錄那些超過預設定的極限值的調用。它實現了circuit break模式,使得可以將客戶端從無響應服務的無盡等待中停止。如果一個服務的錯誤率超過預設值,Hystrix將中斷服務,并且在一段時間內所有請求立刻失效。Hystrix可以為請求失敗定義一個fallback操作,例如讀取緩存或者返回默認值。如果你在用JVM,就應該考慮使用Hystrix。如果你采用的非JVM環境,那么應該考慮采用類似功能的庫。

?

總結

對于大多數微服務基礎的應用,實現一個API Gateway都是有意義的,它就像是進入系統的一個服務提供點。API Gateway負責請求轉發、請求合成和協議轉換。它提供給應用客戶端一個自定義的API。API Gateway可以通過返回緩存或者默認值的方式來掩蓋后端服務的錯誤。在本系列的下一篇文章中,我們將討論服務間的通信問題。

原文鏈接:Building Microservices: Using an API Gateway?(翻譯:陳杰;審校:楊峰)

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/449738.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/449738.shtml
英文地址,請注明出處:http://en.pswp.cn/news/449738.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

sql數據庫挖坑

sql數據庫存入數據時,因為列 名不允許有括號,無法識別,需要對括號進行剔除 df df.rename(columnslambda x: x.replace("(","").replace(),))

力扣——頂端迭代器

給定一個迭代器類的接口,接口包含兩個方法: next() 和 hasNext()。設計并實現一個支持 peek() 操作的頂端迭代器 -- 其本質就是把原本應由 next() 方法返回的元素 peek() 出來。 示例: 假設迭代器被初始化為列表 [1,2,3]。調用 next() 返回 1&#xff0c…

五步讓你成為專家級程序員

摘要:Mark Lassoff是一位高級技術培訓師,從事培訓工作已有10余年。他培訓的客戶包括美國國防部、Lockheed Martin等。在多年的培訓生涯中,他總結了一些如何快速學習一門語言的技巧,這些技巧非常簡單,但是卻讓人受益匪淺…

Ionic混合移動app框架學習

第一章 緒論創建移動app有三種安卓原生App,使用java語言,目前推薦kotlin語言,開發工具Android studioIOS原生App,使用Objective-C或者Swift語言,開發工具Xcode混合移動App,使用web通用語言(HTML…

IPC 中 LPC、RPC 的區別和聯系

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 進程間通信(IPC,Inter-Process Communication),指至少兩個進程或線程間傳送數據或信號的…

Laravel 使用 Aliyun OSS 云存儲

對象存儲 ( Object Storage Service, 簡稱 OSS ) OSS 相信大家都聽過, 它是阿里云對外提供的海量, 安全和高可靠的云存儲服務. 大家可以把自己網站的資源存上面加快自己網站速度, aliyun 官網也有文檔不過對于新手來說有點難, 那么這里我給大家推薦一個組件和組件的使用. johnl…

python多級索引修改

創建多級索引 cols pd.MultiIndex.from_tuples([("a","b"), ("a","c")]) pd.DataFrame([[1,2], [3,4]], columnscols) abc012134 df.columns df.columns.droplevel() df bc012134

在線學習新編程 技巧全攻略

摘要:有句俗語叫:“技多不壓身”,如果你有時間和興趣,不妨多了解和掌握編程技能,或許隨時可能有用。本文為你收集了一些編程技巧,讓你輕松學編程。 有句俗語叫:“技多不壓身”,如果你…

第 3 章 鏡像 - 018 - 鏡像命名的最佳實踐

為鏡像命名 創建鏡像時 docker build 命令時已經為鏡像取了個名字,例如: docker build -t ubuntu-with-vi 這里的 ubuntu-with-vi 就是鏡像的名字。通過 dock images 可以查看鏡像的信息。 1 rootubuntu:~# docker images ubuntu-with-vi 2 REPOSITORY …

Jmeter邏輯控制器-ForEach Controller

ForEach Controller 介紹 ForEach Contoller 即循環控制器,顧名思義是定義一個規則。主要有以下一個參數:名稱:隨便填寫注釋:隨便填寫輸入變量前綴:可以在“用戶自定義變量”中定義一組變量。循環控制器可以從中獲取到…

微服務實戰(三):深入微服務架構的進程間通信

見:http://www.dockone.io/article/549簡介 在單體式應用中,各個模塊之間的調用是通過編程語言級別的方法或者函數來實現的。但是一個基于微服務的分布式應用是運行在多臺機器上的。一般來說,每個服務實例都是一個進程。因此,如下…

python輸出與刪除某行或某列

python輸出字符,主要為結合變量形成新的變量名 year 2016 event Referendum fResults of the {year} {event}Results of the 2016 Referendum yes_votes 42_572_654 no_votes 43_132_495 percentage yes_votes / (yes_votes no_votes) {:-9} YES votes {:2…

為什么應該用模塊取代C/C++中的頭文件?

摘要:本文整理自Apple C工程師Doug Gregor的演講Slide,他表示希望使用模塊(Module)這一概念替代C/C中的頭文件,現已被C標準化委員會任命為Module研究組的主席,研究該提議的可能性。考慮到Apple的開源項目LL…

北向資金進行股票、期貨指數、基金策略

#%%導入包 import tushare as ts import datetime import pandas as pd import numpy as np import akshare as ak import warnings warnings.filterwarnings("ignore")#獲取北向資金數據 df_data2 ak.stock_em_hsgt_north_acc_flow_in(indicator"北上") d…

Kong Api 初體驗、Kong安裝教程

見:https://blog.csdn.net/forezp/article/details/79383631Kong是一個可擴展的開源API層(也稱為API網關或API中間件)。 Kong運行在任何RESTful API的前面,并通過插件擴展,它們提供超出核心平臺的額外功能和服務。 Kon…

Spring Boot2.0+中,自定義配置類擴展springMVC的功能

在spring boot1.0,我們可以使用WebMvcConfigurerAdapter來擴展springMVC的功能,其中自定義的攔截器并不會攔截靜態資源(js、css等)。 Configuration public class MyMvcConfig extends WebMvcConfigurerAdapter {Overridepublic v…

從谷歌宕機事件認識互聯網工作原理

摘要:谷歌服務器經歷了短暫的宕機事件,持續大概27分鐘,對部分地區的互聯網用戶造成了影響。此次事件的原因深究起來需要進入互聯網絡那深邃的、黑暗的角落。 譯者注:本文中提到CloudFlare是一家總部位于美國舊金山的內容分發網絡(…

聊聊技術寫作的個人體會

有群友問過,是什么原因使我開始寫技術公眾號,又是什么動力讓我堅持寫的。 在我看來,寫作是一件不能敷衍的事,通過寫作來學習,反而要比單純地學習的效果要好。為了寫成一篇“拿得出手”的文章,我要反復查找資…

「2019冬令營提高組」全連

傳送門 顯然的 $dp$ 設 $f[i]$ 表示點擊第 $i$ 個音符時的最大價值,$t[i]$ 表示音符 $i$ 的準備時間 那么可以枚舉 $1$ 到 $i-t[i]$ 的所有音符,如果 $j$ ,如果 $jt[j]$ 小于等于 $i$ ,那么 $f[i]max(f[i],f[j]t[i]*val[i])$ 考慮…

Docker常用命令、超實用、講解清晰明了(rm、stop、start、kill、logs、diff、top、cp、restart ...)

前些天發現了一個巨牛的人工智能學習網站,通俗易懂,風趣幽默,忍不住分享一下給大家。點擊跳轉到教程。 1. 查看docker信息(version、info) # 查看docker版本 $docker version # 顯示docker系統的信息 $docker i…