◎ API網關的意義
◎ API網關的職責
◎ API網關的缺點
◎ 使用API網關認證身份
◎ API網關技術實戰
網關的英文是Gateway,翻譯為門、方法、通道、途徑。API網關就是接口的通道或接口的大門。要想訪問API,就必須通過API網關,為什麼要有API網關,這樣做有什麼作用?帶着這些問題,我們來學習本章的内容。
API網關的意義API網關并沒有引申含義,通俗來講,它就是應用系統所有接口的唯一關卡,就像一道門,想要調用到接口,就必須從這扇門進入。為什麼要有這樣一道門?
在微服務中,服務端被拆分成一組職責單一的微小服務,這樣做的好處不再贅述。但我們的服務由少變多,必然會增加系統的複雜度。原先客戶端隻需關心與一個單體的服務交互即可,現在需要去了解每個服務的具體信息,包括認證規則、主機地址、集群方式等。即便擁有再完善的服務注冊與發現機制,客戶端也需要對後端服務的各個職責劃分,才能知道哪個API應該調用哪個服務。在大型項目中,客戶端往往需要花費巨大的工作量來集成這些後端。
設想一下,在一個沒有API網關的系統中,前後端調用關系如圖5.1所示。
複雜的調用關系讓客戶端難以維護,光看就覺得很亂。假設我們要開發移動端的代碼,調用後端的服務,就需要維護與各個服務的調用關系。服務的個數一旦增加,如系統中有幾十個,甚至上百個服務,關系維護起來将花費相當多的時間。最主要的是,前端根本不想關心這些問題,對于前端開發來講,隻想調用可用的接口,這本身是後端服務的架構邏輯,前端會因為這種架構模式變得異常複雜,而且這個複雜度會在每個客戶端中重複出現。
同時,認證規則無法複用,圖5.1所示為一個商場系統,一般情況下,系統會根據不同的終端設計不同的用戶認證規則,如PC端可以通過用戶名密碼的方式進行用戶認證,移動端可以使用手機号加短信驗證碼的方式進行用戶認證,第三方可以通過證書密鑰等方式進行用戶認證,那麼這些認證方式通常都由後端服務來實現。
如果客戶端直接調用用戶敏感的接口,這些接口所在的服務必須擁有認證的能力才行。換句話說,這些後端服務都需要實現多套用戶認證的邏輯,并且還需要根據不同終端的請求使用不同的認證方式。
為了使微服務更加通用,後端服務的代碼中就必然會被耦合上一些客戶端的判斷邏輯,因而顯得不夠單純,再者每個服務都存在着大量重複的認證邏輯,一旦有些客戶端的認證方式發生變化,就需要去維護每個服務中的認證代碼,如圖5.2所示。
前端受到後端架構的“污染”,職責增加,開發難度增大。當然,可能有不少系統都與圖5.1所示的系統類似或更加簡單,服務也就幾個甚至更少,系統本身就隻有一個客戶端,或者根本沒有做前後端分離,這樣的系統調用鍊就很簡單,客戶端維護服務信息也很容易。
即使這樣仍然需要API網關,首先在生産環境中,服務都是多實例部署,以增加系統的可用度,一旦服務部署了多個實例,就需要有負載均衡的策略。
在微服務架構中,一般都采用客戶端負載均衡的方式。也就是說,需要前端來負責負載均衡,有了負載均衡,還需要考慮服務熔斷、降級、恢複等情況,這些服務治理職責都将交由前端來承擔,如圖5.3所示。
雖然如今前端的能力越來越強,一些框架也能夠處理複雜的服務治理邏輯,但前端更應該關注用戶的交互、數據的渲染等表現層的邏輯,而不應被後端的架構所影響,從而做很多不擅長或不應該負責的工作。
API網關的出現就很好地解決了這些問題。首先,前端不再面對複雜的調用關系,隻需請求API網關即可;其次,系統本身不需要重複地關心客戶端的認證方式,可以将認證邏輯放到API網關來做;最後,服務管理的職責也和前端解耦,可以在API網關集成Spring CloudNetflix Hystrix等組件,就能輕松擁有相關的服務治理能力,API網關架構圖如圖5.4所示。
API網關起到了很好的前後端隔離作用,既保護後端服務不會摻雜前端的判斷邏輯,也隔離前端與微服務治理相關的職責,通過統一的網關,對所有的請求進行轉發、過濾和治理,早期我們在單體式架構中常用的Nginx也是一種API網關模式的實現。
API網關的職責在解釋了為什麼要使用API網關之後,其職責也體現出來了。API網關的職責主要有3個:請求路由、請求過濾和服務治理。
請求路由
API網關本身并不具有服務的能力,一旦接收到客戶端的請求,API網關會根據一定的規則(我們稱它為路由規則)将這些請求轉發給後端的微服務。
客戶端不需要關心後端有幾個微服務,也不需要關心這些服務的主機地址,隻需維護一個API網關的地址。通過API網關,将請求路由到對應的服務端,通常我們會采用URL的路由規則,例如,将請求路徑/users/ **轉發給用戶服務,将請求地址/goods/ **轉發給商品服務,API網關URL路由示意圖如圖5.5所示。
除了請求路徑的路由規則,我們還可以通過Reqest Header、Cookie等方式來設置路由的規則。例如,在Request Header或Cookie中可以設置Service-ID的鍵值,然後API網關就可以通過RequestHeader或Cookie來轉發這些請求。總而言之,客戶端隻需将請求發送到API網關即可,不需要關心不同的服務地址或端口。當然,服務端通常會與前端定義好契約,其中包括URL或其他路由規則的定義,這樣客戶端不需要任何成本就可以使用服務端的接口。
請求過濾
我們已經知道API網關的一個重要職責就是用戶認證,即通過一定的方式将不符合條件或不安全的請求攔截,而大部分API網關都是通過過濾器的方式來實現請求的攔截。當客戶端首次請求需要用戶認證權限的接口時,會先到達API網關的過濾器,然後API網關通過自己實現的認證邏輯判斷當前請求的用戶是否為已經認證過的合法用戶,若校驗失敗,則請求被攔截,若校驗通過,則過濾器不攔截該請求,請求正常向後執行邏輯,API網關請求認證流程如圖5.6所示。
API網關也可以調用獨立的認證服務來支撐自己的認證邏輯,如通過查詢用戶信息來校驗用戶名密碼、驗證密鑰等操作,或者有時系統本身就沒有自己的用戶體系,需要集成第三方系統的單點登錄服務或用戶、權限等基礎服務,那麼我們完全可以将API網關和認證邏輯解耦,API網關依然負責攔截請求,但具體認證規則的判斷可以調用後端的認證服務來完成,API網關與認證服務交互過程如圖5.7所示。
當然,用戶的登錄認證也可以由API網關來負責,關于認證的詳細實現将在5.3節介紹,這裡不再贅述。
其實,一旦系統的所有請求都采用統一的入口,除了安全認證,我們還可以做很多事情,例如,可以通過過濾器的方式再過濾一下敏感的信息,如請求頭中的Cookie、Authorization等,還可以修改請求或響應的信息,如限制請求大小、失敗重試等操作,也可以設置過濾器的順序,将不同的規則寫在過濾器中,以組合不同的功能需求,API網關過濾器組合使用示意圖如圖5.8所示。
服務治理
請求路由和請求過濾可以說是API網關的兩個重要功能,除了它們,還可以使用與後端微服務架構更加切合的技術來使API網關擁有服務治理的能力。API網關同樣可以作為一個服務消費者,通過集成負載均衡器、斷路器、注冊中心和健康監控等組件完成服務的治理工作。通過将API網關集成注冊中心,我們可以動态地進行服務發現,從而更優雅地完成路由、負載均衡等操作,如圖5.9所示。
在API網關也作為注冊中心的一個客戶端注冊到注冊中心後,就能夠動态地發現與監控各個服務的信息。例如,服務A和服務B也注冊到注冊中心,根據注冊中心提供的服務信息,API網關就能很方便地進行遠程調用、負載均衡等操作。
API網關作為服務的統一調用者,還可以方便地集成斷路器,做到統一的服務熔斷和降級,如圖5.10所示。
如果沒有API網關,服務熔斷就隻能在服務間使用,或者需要前端浏覽器等終端來負責,并且每個終端可能都要實現相同的功能;如果有API網關,就可以像圖5.10所示的那樣對所有的後端服務進行統一的熔斷處理,包括服務降級、自動恢複等問題就不用每個終端去實現,而且讓前端來做服務治理顯然是很奇葩的做法。
當然,對于不同的客戶端,它的用戶認證方式、服務治理策略及接口的規範可能都不一樣,這時我們可以針對不同的終端配置不同的API網關,多終端API網關示意圖如圖5.11所示。
關于多個API網關的架構模式還有一個名稱:BFF(Backend For Frontend,用于前端的後端),關于BFF的實踐将在第6章中詳細介紹。
API網關的缺點前面介紹了使用API網關的目的和職責,那麼API網關有沒有缺點?任何架構模式都不是萬能的,包括微服務架構本身都存在着不足,API網關總體來說有兩個缺點:一是增加了開發的複雜度,二是有一定額外的性能消耗,如圖5.12所示。
首先,顯而易見地增加了項目的複雜度。在項目中使用過API網關的開發者不難發現,API網關需要進行額外開發和維護,在開發一個接口時,以往隻需和前端進行調試,現在還需要和API網關調試,而且還涉及新的服務配置、部署和管理等工作。
其次,在前後端之間增加了一層調用鍊,哪怕隻是簡單的轉發,也必然增加了一定的性能消耗,而且通常我們使用HTTP進行服務調用,HTTP的交互性能并不是很好,所以在一些對性能有極緻要求的項目中,可能需要一些額外的優化工作,如緩存、請求合并等操作。
使用API網關認證身份提到API網關,就不得不提及身份認證,因為安全保證才是一個網關最原始和最核心的功能,5.2.2節中已經介紹了API網關請求過濾的架構設計,那麼在與前端的交互中,API網關如何對請求進行安全保障呢?
分清認證與授權
通常我們說到軟件的安全管理,一般包括兩個概念:一是認證,二是授權。這兩個概念也經常被大家混淆,而且它們的英文單詞很像,認證的英文是Authentication,授權的英文是Authorization,很多人在代碼中會使用簡寫的Auth來替代這兩個單詞。筆者在每次遇到含有Auth簡寫的代碼時都會感到異常焦躁,必須要深入解讀代碼才能知道這段代碼到底是在處理認證還是在處理授權。
那麼,什麼是認證,什麼是授權?
認證又稱身份認證,是指通過一定的方式完成對用戶身份的确認。在軟件系統中,不是所有的服務都是開放式的,大部分情況下需要識别當前請求人是否為系統中的合法用戶,這個識别的過程就是認證。
授權是指對資源的訪問進行權限的定義,并通過授予用戶不同的權限做到資源的訪問控制。例如,公司的在職員工都能登錄公司的财務系統,但隻有财務人員才能查看公司的财務報表,其他員工隻能查看自己的工資條。在軟件系統中,授權在認證之後,隻有識别了用戶的身份,才能知道用戶的權限,并對用戶的訪問進行控制,認證與授權的職責示意圖如圖5.13所示。
圖5.13 認證與授權的職責示意圖
在圖5.13中,HTTP的狀态碼幫我們定義了不同的數值來區别認證和授權的異常,通常使用401表示認證失敗,使用403表示沒有訪問權限。
API網關是否需要管理授權認證在一開始就已經明确了是API網關的核心職責,因為認證邏輯一般與不同的客戶端類型有關,有足夠的通用性,不需要基礎服務各自實現,而且在圖5.11中,API網關通常是和客戶端類型一對一的設計,是所有接口的唯一入口,所以認證十分适合放在API網關來實現。
那麼授權是否也可以交給API網關來實現呢?
首先,我們要明白授權需要做哪些事情。授權是對資源訪問權限的控制,大緻上可以分為資源路徑授權和資源授權兩種類型,又稱URL授權和數據授權。
例如,一款遊戲軟件隻有VIP會員才能修改頭像,假設現在有修改頭像的接口A,隻允許角色是VIP會員的用戶才能訪問,這就是URL級别的授權,資源路徑的授權把權限放在接口層面,控制請求能訪問的具體接口。所謂資源授權,其實就是比資源的接口更深層次的權限控制,如VIP會員雖然能訪問修改用戶頭像的接口,但每個用戶隻能修改自己的頭像,如果VIP會員在請求中傳入的是其他用戶的ID,這顯然不允許。我們判斷當前修改的數據是否符合業務規則,隻能修改自己的頭像就是當前的業務規則,這就是資源授權,即數據授權。
從架構層面來看,API網關是所有接口的統一入口,适合做一些全局限制,所以有一些項目會把授權放在API網關來實現,事實證明,它确實可以做到訪問的權限控制。在架構設計中,并不是一味地封裝或分離就是好的,要具體場景具體分析,比較通用的判斷方法就是如果設計導緻代碼邏輯需要重複維護多個地方,就不是很好的設計。例如,之前我們分析的授權主要與業務規則相關,與是否為移動端或PC端沒有關系,系統不會因為是手機用戶就允許修改其他人的頭像。如果把授權放在API網關層實現,那麼實現授權如圖5.14所示。
由于授權是針對業務規則進行控制的,無論是接口級的資源路徑授權還是數據級的資源授權都需要對代碼有一定的侵入性,因此一般授權沒有很好的方式分離成單獨服務。首先,即使是相同的授權規則,也需要在不同的API網關中集成相同的授權實現;其次,授權與業務規則強相關,各個微服務更加了解自己的業務規則及數據規則,如果API網關由不同的團隊開發,要做好授權顯然比較困難,綜合這些原因,授權其實更适合放到業務層,即微服務各自去控制和管理,如圖5.15所示。
圖5.15 服務的業務邏輯層負責授權示意圖
這樣做的好處是首先授權邏輯可以更加通用,調用者不需要重複實現和維護授權的規則,其次服務端實現授權更加方便,而且業務邏輯層也更了解數據規則。
本文給大家講解的内容是API網關更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!