架構設計-API網關

1、前言

所在公司目前接入層是阿里雲的SLB,然後經過Nginx+Lua轉發到後端服務(Lua主要是限流)。 隨著業務的發展,發現nginx配置越來越複雜,但又沒有統一的管理,於是把Nginx這層改造成基於 OpenResty的Nginx 應用的API Gateway。於是上網總結和梳理網關相關知識。

問題:

由於我們使用的服務系統架構,所以沒辦法像傳統單體應用一樣依靠數據庫的 join 查詢來得到最終結果,那麼如何才能訪問各個服務呢?

按照微服務設計的指導原則,我們的微服務可能存在下面的問題:

服務使用了多種協議:因為不同的協議有不同的應場景用,比如可能同時使用 HTTP, AMQP, gRPC 等。

服務的劃分可能隨著時間而變化。

服務的實例或者Host+端口可能會動態的變化。

那麼,對於前端的UI需求也可能會有以下幾種:

粗粒度的API,而微服務通常提供的細粒度的API,對於UI來說如果要調用細粒度的api可能需要調用很多次,這是個不小的問題。

不同的客戶端可能需要不同的數據。Web,H5,APP,OpenAPI

不同設備的網絡性能,對於多個api來說,這個訪問需要轉移的服務端會快得多

以上,就是我們構建微服務的過程中可能會遇到的問題。

2、概念

API Gateway(API GW / API 網關),顧名思義,是企業 IT 在系統邊界上提供給外部訪問內部接口服務的統一入口。在微服務概念的流行之前,API網關的實體就已經誕生了,例如銀行、證券等領域常見的前置機系統,它也是解決訪問認證、報文轉換、訪問統計等問題的。

百度百科:API網關是一個服務器,是系統的唯一入口。從面向對象設計的角度看,它與外觀模式類似。API網關封裝了系統內部架構,為每個客戶端提供一個定製的API。它可能還具有其它職責,如身份驗證、監控、負載均衡、緩存、請求分片與管理、靜態響應處理。

API網關方式的核心要點是,所有的客戶端和消費端都通過統一的網關接入微服務,在網關層處理所有的非業務功能。通常,網關也是提供REST/HTTP的訪問API。服務端通過API-GW註冊和管理服務。

3、網關使用場景

API網關的流行,源於近幾年來,移動應用與企業間互聯需求的興起。移動應用、企業互聯,使得後臺服務支持的對象,從以前單一的Web應用,擴展到多種使用場景,且每種使用場景對後臺服務的要求都不盡相同。這不僅增加了後臺服務的響應量,還增加了後臺服務的複雜性。

當應用架構是由一系列的微服務構建的時候,我們就應當考慮對外提供的服務如何與微服務進行交互。

我們根據使用場景分類大體如下:

1、Web App APIGateway 和 Mobile App APIGateway:

聚合作用:寫簡單的業務邏輯,跨多個service獲取數據拼裝結果。

在Mobile app產品信息頁面仍然要展現很多的信息。例如,基本的產品信息,該頁也會展示產品其他相關信息:

購物車;歷史訂單;顧客評論;低庫存預警;運送選項;各種產品推薦;可替代的購買選項;

當使用單體應用架構時:

移動客戶端通過給應用發送一個REST請求來獲取數據,比如:

GET api.company.com/productdetails/productId

負載均衡器路由這個請求到幾個相同應用實例其中的一個。單體應用接著查詢多個數據庫表並返回響應給客戶端。

當使用微服務架構的時候:

顯示在產品詳細信息頁面的數據來自於多個微服務。如下是一些潛在的服務,它們也有可以展示在特定產品信息頁面的數據:

購物車服務、訂單服務、目錄服務、評論服務、庫存服務、運送服務、推薦服務。

這個需要使用Mobile app API Gateway:它通常向移動客戶端暴露出一個粗粒度的API。

API網關可以提供類似這樣的接口:

GET api.company.com/productdetails/productId

可以使移動客戶端在一次調用中獲取所有的產品信息。API網關通過調用多個服務—產品服務、推薦服務、評論服務等來處理請求,並封裝結果。

優點:

1、解耦作用:它封裝了應用的內部結構,客戶端直接和網關通信,而不必調用特定的服務。

2、提供給每種客戶端特定優化的API。

3、減少請求環路、簡化客戶端邏輯。比如說,API Gateway使得客戶端用一次請求就可以從多個service處獲取數據。

缺點:

1、必須被開發、部署和管理成一個高度可用的組件,也有成為開發瓶頸的危險。

2、為了暴露出每個微服務的,開發者必須更新API網關。

2、Partner OpenAPI:

轉發路由作用:對外提供的接口服務,一般直接把請求轉發到合適的service,但是此時的API GW需要增加配額、限流、令牌等一系列安全管控功能。對外提供隔離作用:請求路由,安全認證,負載均衡,限流、監控、權限控制等等。

4、API網關需要考慮的因素

1、安全性問題

企業在把服務暴露給外部使用時,首先要確保服務使用的安全,防止外部的惡意訪問對公司業務的影響,特別是涉及交易方面的服務,更是要全面考慮安全性。為確保安全,需要考慮在通訊鏈路的建立、通訊數據的加密、數據的完整性、不可抵賴性等方面。

2、性能問題

作為企業API的入口,所有的請求都會經過API網關進行轉發,可想而知,對API網關的訪問壓力是巨大的,有的網站甚至達到每分鐘上千萬的訪問量。特別是在一些互聯網企業,海量的移動終端每時每刻都需要與後端的服務進行交互,如果不能保證網關的高性能,企業在網關層需要投入大量的設備和成本。曾在一家互聯網公司發生過,由於網關性能問題,網關的機器數量,需要與後臺服務器的數量保持同步增長。這種情況顯然是企業服務忍受的。

3、高可用問題

API網關作為邏輯上的單點,一旦發生問題,將造成企業服務的不可用,對企業來說可能造成的致命的影響。計算短時間的不可用,也會給企業帶來直接的經濟損失。所以,如何保證API網關的7*24小時的穩定運行,網關的自動伸縮、API的熱更新等問題,都是企業級的網關需要考慮的。

4、擴展性問題

前面說到,企業網關提供了一個腳手架,一些非功能性的問題,例如日誌、安全、負載均衡策略、鑑權等。這些插件會隨著企業業務規模等的變化進行不斷的強化與調整。這就需要網關層提供這樣一種機制,使得可以靈活地進行這些調整和變化,而不用頻繁對網關層進行改動,確保網關層的穩定性。

5、API高效運維的問題

API在上線、發佈過程中,都需要涉及到網關層的配合,例如,需要網關層知道API發佈的地址,API的接口形式、報文格式,也需要網關層對後臺API進行封裝。在API調整後,需要作出相應的修改。所以,API網關設計時,需要明確網關層與服務層的職責切分與協作模式,使得API的管理、發佈更加高效。

6、API全生命週期的管理

API服務的全生命週期,包括服務的開發、測試、上線發佈;服務使用的申請、開通;服務分類分級別的管理、服務使用情況的監控、計費等等。

一個企業可能會暴露成百上千個API,日常也會經常進行API的發佈、升級、改造、下架等操作。對不同的服務,不同的訪問者,需要提供不同的服務訪問策略。有的商業API公司,還需要對API的使用進行付費。所以,與API網關配套的,需要一套完善的自助系統,提供給服務的提供者、管理者、使用者,來對服務的發佈、使用、和運營。

5、業界常用的API網關方案

通常情況下, API 網關要做很多工作,它作為一個系統的後端總入口,承載著所有服務的組合路由轉換等工作,除此之外,我們一般也會把安全,限流,緩存,日誌,監控,重試,熔斷等放到 API 網關來做,那麼可以試想在高併發的情況下,這裡可能會出現一個性能瓶頸。

另外,如果沒有開源項目的支撐前提下,自己來做這樣一套東西,是非常大的一個工作量,而且還要做 API 網關本身的高可用等,如果一旦做不好,有可能最先掛掉的不是你的其他服務,而就是這個API網關。

1:基於OpenResty 的 Nginx

性能和高可用性上:

Nginx性能極高,Nginx先天的事件驅動型設計、全異步的網絡I/O處理機制、極少的進程間切換以及許多優化設計,都使得Nginx天生善於處理高併發壓力下的互聯網請求。Nginx的穩定性也在各大網站得到驗證。官方提供的常用模塊都非常穩定,每個worker進程相對獨立,master進程在1個worker進程出錯時可以快速“拉起”新的worker子進程提供服務。支持熱部署,可以不停機更新配置文件、更新日誌文件、更新服務器程序版本。

擴展性上:

Nginx的設計極具擴展性,它完全是由多個不同功能、不同層次、不同類型且耦合度極低的模塊組成。因此,當對某一個模塊修復Bug或進行升級時,可以專注於模塊自身,無須在意其他

易用性上:

Nginx使用最自由的BSD許可協議,允許用戶在自己的項目中直接使用或修改Nginx源碼,有大量的插件可以利用。但是,Nginx模塊需要用C開發,而且必須符合一系列複雜的規則。雖然通過第三方模塊,可以支持Nginx與Perl、Lua等腳本語言集成工作,但對使用者的要求還是很高。

2:Spring Cloud Zuul


架構設計-API網關


基本功能

驗證與安全保障: 識別面向各類資源的驗證要求並拒絕那些與要求不符的請求。

審查與監控: 在邊緣位置追蹤有意義數據及統計結果,從而為我們帶來準確的生產狀態結論。

動態路由: 以動態方式根據需要將請求路由至不同後端集群處。

壓力測試: 逐漸增加指向集群的負載流量,從而計算性能水平。

負載分配: 為每一種負載類型分配對應容量,並棄用超出限定值的請求。

靜態響應處理: 在邊緣位置直接建立部分響應,從而避免其流入內部集群。

Netflix公司還利用Zuul的功能通過金絲雀版本實現精確路由與壓力測試。

雖然提供的功能還算豐富,但都比較弱,很難滿足高要求的場景。

性能和高可用性

Zuul處理每個請求的方式是針對每個請求是用一個線程來處理。通常情況下,為了提高性能,所有請求會被放到處理隊列中,從線程池中選取空閒線程來處理該請求。2016年底,Netflix將它們的網關服務Zuul進行了升級,全新的Zuul 2將HTTP請求的處理方式從同步變成了異步,以提升其處理性能。除了Netflix公司,目前Zuul在企業中用的還比較少,性能和穩定性方面還有待進一步觀察。

擴展性上,

從Zuul的架構圖上可以看出,Zuul更像是一個過濾器框架,其自身的路由、日誌、反向代理、ddos預防等功能都是通過過濾器實現的。提供了PRE、ROUTING、POST和ERROR四個擴展點,可以很容易的添加自定義的過濾器。

易用性上

Zuul的搭建非常簡便,使用和配置也很簡單。Zuul的開源社區比較活躍,一直在更新狀態,但版本不算太穩定,在使用的過程中,還有一些坑要踩。例如重定向問題、異常處理問題,還沒有解決的很好,需要自己重寫一些filter。

3.Mashape Kong


架構設計-API網關


Kong的一個非常誘人的地方就是提供了大量的插件來擴展應用,通過設置不同的插件可以為服務提供各種增強的功能。Kong默認插件插件包括:

l 身份認證:Kong提供了Basic Authentication、Key authentication、OAuth2.0 authentication、HMAC authentication、JWT、LDAP authentication認證實現。

l 安全:ACL(訪問控制)、CORS(跨域資源共享)、動態SSL、IP限制、爬蟲檢測實現。

l 流量控制:請求限流(基於請求計數限流)、上游響應限流(根據upstream響應計數限流)、請求大小限制。限流支持本地、Redis和集群限流模式。

l 分析監控:Galileo(記錄請求和響應數據,實現API分析)、Datadog(記錄API Metric如請求次數、請求大小、響應狀態和延遲,可視化API Metric)、Runscope(記錄請求和響應數據,實現API性能測試和監控)。

l 轉換:請求轉換、響應轉換

Kong本身也是基於Nginx的,所以在性能和穩定性上都沒有問題。Kong作為一款商業軟件,在Nginx上做了很擴展工作,而且還有很多付費的商業插件。Kong本身也有付費的企業版,其中包括技術支持、使用培訓服務以及 API 分析插件。

從對上面三種方案的比較中可以看到,Spring Cloud Zuul非常適合創業初期的團隊,快速搭建一個“基本可用”的API網關。Nginx適合有較強研發團隊,自主開發企業自己的API網關。Kong適合於沒有自身研發團隊,但需要擁有企業級API網關能力的公司。

4、Orange:

和Kong類似也是基於OpenResty的一個API網關程序,是由國人開發的。

5、apiaxle:

Nodejs 實現的一個 API 網關。

6、api-umbrella:

Ruby 實現的一個 API 網關。

7、Tyk:

Tyk是一個開放源碼的API網關,它是快速、可擴展和現代的。Tyk提供了一個API管理平臺,其中包括API網關、API分析、開發人員門戶和API管理面板。Try 是一個基於Go實現的網關服務。

比較:

Spring Cloud Zuul非常適合創業初期的團隊,快速搭建一個“基本可用”的API網關。

OpenResty+Nginx適合有較強研發團隊,自主開發企業自己的API網關。

Kong適合於沒有自身研發團隊,但需要擁有企業級API網關能力的公司。

Try擴展需要會Go語言

但是上面的這些 API 網關都缺少超時,熔斷,重試,聚合查詢等功能。這個需要我們業務自己開發。


架構設計-API網關


簡單解釋:

OpenResty Api Gateway

HTTP 請求先由DNS在拿到第一手流量後負載均衡到基於 OpenResty 的 API Gataway 網關集群,在這個流程我們可以使用像 Kong,Orage,Tyk 這些開源的支持高併發高訪問量 API 網關程序在做第一層流量的防護,在這一級我們可以做一些像身份認證,安全,監控,日誌,流控等策略。除了這些我們還可以做一些服務的發現和註冊(這個要看不同網關的支持程度),接口的版本控制,路由重寫等。

OpenResty Api Gateway也可以直接訪問內部服務,比如一些對外開放平臺api。

Web/Mobile Api Gateway

然後再由這些 OpenResty API 網關把請求再負載到不同的 Web/Mobile Api Gateway,在這裡我們做聚合服務這個操作,具體體現也就是圖中的黃色區域是需要由各個語言的開發人員來需要寫代碼實現的。這期間對於有需求的接口,我們可以應用超時,緩存,熔斷,重試等策略。

從 Web/Mobile Api Gateway 到後端微服務集群這中間就屬於內部的通訊了。

6、設計API網關

一:功能需求

1、API 生命週期管理功能:

覆蓋 API 的定義、測試、發佈的整個生命週期管理,便捷的日常管理、版本管理,支持熱升級和快速回滾

2、開發和使用支持功能:

提供頁面調試工具,自動生成 API 文檔和 SDK,大大降低人力成本。

3、安全防護功能:

API 請求到達網關需要經過嚴格的身份認證、權限認證,才能到達後端服務。支持算法簽名,支持 SSL 加密。

4、流量控制功能:

可控制單位時間內 API 允許被調用次數。用來保護企業的後端服務,實現業務分級和用戶分級。 支持對 API 流控,您可以根據 API 的重要程度來配置不同流控,從而保障重要業務的穩定運行; 支持用戶、應用和例外流控,您可以根據用戶的重要性來配置不同流控,從而可以保證大用戶的權益; 流控粒度:分鐘、小時、天。

5、請求管理功能:

可根據配置進行參數類型、參數值(範圍、枚舉、正則、Json Schema)的校驗,減少後端對非法請求、無效請求的資源消耗和處理成本。可以在 API 網關定義參數映射規則,網關通過映射規則將後端服務通過映射翻譯成任何形式,以滿足不同用戶的不同需求,從而避免功能重複開發。

6)監控告警功能:

提供實時、可視化的 API 監控,包括:調用量、調用方式、響應時間、錯誤率,讓您能夠清楚的瞭解 API 的運行狀況和用戶的行為習慣。

支持自定義報警規則,來針對異常情況進行報警,降低故障處理時間。

提供可訂閱的數據分析報表和智能分析。

二:高性能設計

傳統的基於線程的併發模型(Thread-based concurrency),為每一個請求分配一個線程或進程。這種模型編程簡單,可以將處理一個完整請求的代碼編寫在一個代碼路徑中。這種模型的弊端是,隨著線程(進程)數的上升,操作系統在這些線程(進程)之間的頻繁切換,將急劇降低系統的性能。


架構設計-API網關


三:高可用設計

1、無狀態設計原則。

網關層為保證高可以,易於伸縮,快速啟動,需要設計成無狀態的。用戶的狀態數據我們通常使用session對象來封裝,網關層要設計成無狀態的,也就是說,不能由網關來負責session的維護。那由誰來維護session相關的信息呢?我們是採用cookie+session服務器的方式;

a) 用戶在登錄頁完成登錄操作後,服務器會生成一個登錄session信息,保存起來,設置個失效時間,並設置到用戶的cookie裡

b) 用戶後續的每次請求裡會帶著這個cookie信息,服務端會對這個cookie信息進行校驗,通過了就認為是合法用戶,執行請求操作

2、優雅下線原則

當需要撤掉一臺網關服務的時候,不是直接結束網關進程,而是先關閉監聽套接字,但是繼續為當前連接的客戶提供服務,所有客戶端的服務完成後,在把進程關閉。

3、Slow start特性

當網關監聽到有一臺新的服務註冊上來時,考慮到有些服務啟動後,剛開始會有許多初始化的工作,此時服務對請求的響應速度是比較慢的。如果一開始就給這臺服務分配太多的壓力,有可能導致服務瞬間被壓垮。為了避免這種情況,網關層需要考慮支持Slow Start特性。即,經過一段時間,逐漸把壓力增加到預設的值。

4、擴展性設計

我們知道,網關對請求的處理,可以分為三個階段:接受請求、路由並轉發請求、接受服務的返回數據並返回給請求者,除此之外,還有一種情況是處理錯誤。所以我們也可以在這四個地方添加擴展點。

(1)接受到請求後

(2)定位到一個服務,並準備轉發之前

(3)接受到服務的返回數據,返回給客戶端之前

(4)當服務調用失敗後

攔截器的處理順序,可以分為兩大類:一類為網關平臺自帶的攔截器,例如安全校驗、日誌記錄等;一類為網關層邏輯開發的,例如格式轉換等。一般來說,網關先執行網關平臺自帶的攔截器,再執行為了業務邏輯編寫的攔截器。當然,網關也需要提供一種機制,可以較容易地調整攔截器的執行順序。最簡單的一種方法,就是給每個攔截器定義一個優先級,網關按優先級順序依次調用各攔截器。

對網關層來說,它接收和處理的數據都是Request對象,網關層在接收到請求後,把請求封裝為Request對象,為了讓後續的filter能夠獲得這個對象,可以考慮把Request對象保存在線程變量中。

有些攔截器,例如一些調試日誌的攔截器,通常情況下都是關閉的,只有在出現問題的時候才需要打開。為了保證網關的高可用,網關層必須具備在線啟用或關閉攔截器的能力。一般,網關需要提供restful接口方式,來關閉和啟用一個攔截器。類似這樣的命令:PUT /apigateway/v1/filters/filterName?enable=value

5、API管理與動態發佈設計

對服務管理來說,分為前端服務管理與後端服務管理。前端服務指的是網關層暴露給客戶端使用的服務API,後端服務指的是服務層提供的業務服務API。一個服務暴露給客戶端使用,除了網關層和服務層提供服務的代碼外,還需要配置前端服務與後端服務的映射關係。

網關層API調用服務層API,有多種方式。例如,可以由按照服務層API的服務契約,生成一段客戶端代碼,發佈給網關層使用。這種方式的弊端是,網關層代碼依賴於服務層代碼,服務層頻繁修改和調整接口時,導致網關層的代碼很難維護。

可以通過配置前後端服務映射的方式,解耦網關層對服務層的依賴。當服務層的API(例如服務名、參數名等)發生變化時,只需調整映射關係,無需對網關層的代碼進行調整。網關層按照映射,自動裝配服務層API所需要的數據格式。這樣,網關層團隊與服務層團隊可以相互不受干擾地開發各自的服務。


分享到:


相關文章: