天天看點

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

作者:等不到的口琴

本文準備圍繞七個點來講網關,分别是網關的基本概念、網關設計思路、網關設計重點、流量網關、業務網關、常見網關對比,對基礎概念熟悉的朋友可以根據目錄檢視自己感興趣的部分。

什麼是網關

網關,很多地方将網關比如成門, 沒什麼問題, 但是需要區分網關與網橋的差別,

網橋工作在資料鍊路層,在不同或相同類型的LAN之間存儲并轉發資料幀,必要時進行鍊路層上的協定轉換。可連接配接兩個或多個網絡,在其中傳送資訊包。

網關是一個大概念,不具體特指一類産品,隻要連接配接兩個不同的網絡都可以叫網關,網橋一般隻轉發資訊,而網關可能進行包裝。

網關通俗了解

根據網關的特性,舉個例子:

假如你要去找集團老闆(這兒隻是舉個例子), 大家都知道老闆肯定不是誰想見就能見的, 也怕壞人嘛, 那麼你去老闆所在的辦公樓,假如是集團總部, 大樓這個門就充當了網關的角色, 大門一般都有看門員 ,看門員會做哪些事情呢?

首先所有想見老闆的人肯定都得從這個門進(統一入口), 這個門相當于将辦公室和外界隔離了,主要為了保護裡面的安全以及正常工作, 來到這個門之後, 門衛肯定會讓你出示相關證件(鑒權檢驗), 意思就是判斷你要見老闆這個請求是否合理, 如果不合理直接就拒絕了, 讓你回家等消息 , 如果鑒權之後, 發現你找老闆其實隻是為了和他談談兩元店的生意, 門衛會跟你說這個用不着找老闆, 你去集團投資部就行了(動态路由, 将請求路由到不同的後端叢集中), 此時會對你進行一些包裝,例如給你出具一個通路證類似的,然後告訴你路該怎麼走,等等。

你看看,網關的作用是不是就是這三個, 最終目的就是減少你與集團的耦合,具體到計算機上就是減少用戶端與服務端的耦合,如果沒有網關意味着所有請求都會直接調用伺服器上的資源,這樣耦合太強了,伺服器出了問題,用戶端會直接報錯, 例如老闆換工作的地方了,如果沒有網關你直接去原來的地方找, 肯定會被告知老闆不在這兒。

為什麼需要網關

當使用單體應用程式架構時,用戶端(Web 或移動端)通過向後端應用程式發起一次 REST 調用來擷取資料。負載均衡器将請求路由給 N 個相同的應用程式執行個體中的一個。然後應用程式會查詢各種資料庫表,并将響應傳回給用戶端。微服務架構下,單體應用被切割成多個微服務,如果将所有的微服務直接對外暴露,勢必會出現安全方面的各種問題,另外内外耦合嚴重。

用戶端可以直接向每個微服務發送請求,其問題主要如下:

  • 用戶端需求和每個微服務暴露的細粒度 API 不比對。
  • 部分服務使用的協定不是Web友好協定。可能使用 Thrift 二進制 RPC,也可能使用 AMQP 消息傳遞協定。
  • 微服務難以重構。如果合并兩個服務,或者将一個服務拆分成兩個或更多服務,這類重構就非常困難了。

服務端的各個服務直接暴露給用戶端調用勢必會引起各種問題。同時,服務端的各個服務可擴充和伸縮性很差。API 網關是微服務架構中的基礎元件,位于接入層之下和業務服務層之上,如前所述的這些功能适合在 API 網關實作。

網關與伺服器叢集

回到我們伺服器上,下面圖介紹了網關(Gateway)作用,可知 Gateway 方式下的架構,可以細到為每一個服務的執行個體配置一個自己的 Gateway,也可以粗到為一組服務配置一個,甚至可以粗到為整個架構配置一個接入的 Gateway。于是,整個系統架構的複雜度就會變得簡單可控起來。

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

這張圖展示了一個多層 Gateway 架構,其中有一個總的 Gateway 接入所有的流量(流量網關),并分發給不同的子系統,還有第二級 Gateway 用于做各個子系統的接入 Gateway(業務網關)。可以看到,網關所管理的服務粒度可粗可細。通過網關,我們可以把分布式架構組織成一個星型架構,由網絡對服務的請求進行路由和分發。下面來聊聊好的網關應該具備哪些功能,也就是網關設計模式。

網關設計思路

一個網關需要有以下的功能:

請求路由

網關一定要有請求路由的功能。這樣一來,對于調用端來說,也是一件非常友善的事情。因為調用端不需要知道自己需要用到的其它服務的位址,全部統一地交給 Gateway 來處理。

服務注冊

為了能夠代理後面的服務,并把請求路由到正确的位置上,網關應該有服務注冊功能,也就是後端的服務執行個體可以把其提供服務的位址注冊、取消注冊。一般來說,注冊也就是注冊一些 API 接口。比如,HTTP 的 Restful 請求,可以注冊相應 API 的 URI、方法、HTTP 頭。 這樣,Gateway 就可以根據接收到的請求中的資訊來決定路由到哪一個後端的服務上。

負載均衡

因為一個網關可以接收多個服務執行個體,是以網關還需要在各個對等的服務執行個體上做負載均衡政策。簡單點就是直接 Round-Robin 輪詢,複雜點的可以設定上權重進行分發,再複雜一點還可以做到 session 粘連。

彈力設計

網關還可以把彈力設計中的那些異步、重試、幂等、流控、熔斷、監視等都可以實作進去。這樣,同樣可以像 Service Mesh 那樣,讓應用服務隻關心自己的業務邏輯(或是說資料面上的事)而不是控制邏輯(控制面)。

安全方面

SSL 加密及證書管理、Session 驗證、授權、資料校驗,以及對請求源進行惡意攻擊的防範。錯誤處理越靠前的位置就是越好,是以,網關可以做到一個全站的接入元件來對後端的服務進行保護。當然,網關還可以做更多更有趣的事情,比如:灰階釋出、API聚合、API編排。

灰階釋出

網關完全可以做到對相同服務不同版本的執行個體進行導流,還可以收集相關的資料。這樣對于軟體品質的提升,甚至産品試錯都有非常積極的意義。

API 聚合

使用網關可以将多個單獨請求聚合成一個請求。在微服務體系的架構中,因為服務變小了,是以一個明顯的問題是,用戶端可能需要多次請求才能得到所有的資料。這樣一來,用戶端與後端之間的頻繁通信會對應用程式的性能和規模産生非常不利的影響。于是,我們可以讓網關來幫用戶端請求多個後端的服務(有些場景下完全可以并發請求),然後把後端服務的響應結果拼裝起來,回傳給用戶端(當然,這個過程也可以做成異步的,但這需要用戶端的配合)。

API 編排

同樣在微服務的架構下,要走完一個完整的業務流程,我們需要調用一系列 API,就像一種工作流一樣,這個事完全可以通過網頁來編排這個業務流程。我們可能通過一個 DSL 來定義和編排不同的 API,也可以通過像 AWS Lambda 服務那樣的方式來串聯不同的 API。

網關設計重點

網關設計重點主要是三個, 高性能、高可用、高擴充:

高性能

在技術設計上,網關不應該也不能成為性能的瓶頸。對于高性能,最好使用高性能的程式設計語言來實作,如 C、C++、Go 和 Java。網關對後端的請求,以及對前端的請求的服務一定要使用異步非阻塞的 I/O 來確定後端延遲不會導緻應用程式中出現性能問題。C 和 C++ 可以參看 Linux 下的 epoll 和 Windows 的 I/O Completion Port 的異步 IO 模型,Java 下如 Netty、Spring Reactor 的 NIO 架構。

高可用

因為所有的流量或調用經過網關,是以網關必須成為一個高可用的技術元件,它的穩定直接關系到了所有服務的穩定。網關如果沒有設計,就會成變一個單點故障。是以,一個好的網關至少要做到以下幾點。

  • 叢集化。網關要成為一個叢集,其最好可以自己組成一個叢集,并可以自己同步叢集資料,而不需要依賴于一個第三方系統來同步資料。
  • 服務化。網關還需要做到在不間斷的情況下修改配置,一種是像 Nginx reload 配置那樣,可以做到不停服務,另一種是最好做到服務化。也就是說,得要有自己的 Admin API 來在運作時修改自己的配置。
  • 持續化。比如重新開機,就是像 Nginx 那樣優雅地重新開機。有一個主管請求分發的主程序。當我們需要重新開機時,新的請求被配置設定到新的程序中,而老的程序處理完正在處理的請求後就退出。

高擴充

因為網關需要承接所有的業務流量和請求,是以一定會有或多或少的業務邏輯。而我們都知道,業務邏輯是多變和不确定的。比如,需要在網關上加入一些和業務相關的東西。是以,一個好的 Gateway 還需要是可以擴充的,并能進行二次開發的。當然,像 Nginx 那樣通過 Module 進行二次開發的固然可以。

另外,在運維方面,網關應該有以下幾個設計原則。

  • 業務松耦合,協定緊耦合。在業務設計上,網關不應與後面的服務之間形成服務耦合,也不應該有業務邏輯。網關應該是在網絡應用層上的元件,不應該處理通訊協定體,隻應該解析和處理通訊協定頭。另外,除了服務發現外,網關不應該有第三方服務的依賴。
  • 應用監視,提供分析資料。網關上需要考慮應用性能的監控,除了有相應後端服務的高可用的統計之外,還需要使用 Tracing ID 實施分布式鍊路跟蹤,并統計好一定時間内每個 API 的吞吐量、響應時間和傳回碼,以便啟動彈力設計中的相應政策。
  • 用彈力設計保護後端服務。網關上一定要實作熔斷、限流、重試和逾時等彈力設計。如果一個或多個服務調用花費的時間過長,那麼可接受逾時并傳回一部分資料,或是傳回一個網關裡的緩存的上一次成功請求的資料。你可以考慮一下這樣的設計。
  • DevOps。因為網關這個元件太關鍵了,是以需要 DevOps 這樣的東西,将其發生故障的機率降到最低。這個軟體需要經過精良的測試,包括功能和性能的測試,還有浸泡測試。還需要有一系列自動化運維的管控工具。

網關設計注意事項

  1. 不要在網關中的代碼裡内置聚合後端服務的功能,而應考慮将聚合服務放在網關核心代碼之外。可以使用 Plugin 的方式,也可以放在網關後面形成一個 Serverless 服務。
  2. 網關應該靠近後端服務,并和後端服務使用同一個内網,這樣可以保證網關和後端服務調用的低延遲,并可以減少很多網絡上的問題。這裡多說一句,網關處理的靜态内容應該靠近使用者(應該放到 CDN 上),而網關和此時的動态服務應該靠近後端服務。
  3. 網關也需要做容量擴充,是以需要成為一個叢集來分擔前端帶來的流量。這一點,要麼通過 DNS 輪詢的方式實作,要麼通過 CDN 來做流量排程,或者通過更為底層的性能更高的負載均衡裝置。
  4. 對于服務發現,可以做一個時間不長的緩存,這樣不需要每次請求都去查一下相關的服務所在的地方。當然,如果你的系統不複雜,可以考慮把服務發現的功能直接內建進網關中。
  5. 為網關考慮 bulkhead 設計方式。用不同的網關服務不同的後端服務,或是用不同的網關服務前端不同的客戶。

另外,因為網關是為使用者請求和後端服務的橋接裝置,是以需要考慮一些安全方面的事宜。具體如下:

  1. 加密資料。可以把 SSL 相關的證書放到網關上,由網關做統一的 SSL 傳輸管理。
  2. 校驗使用者的請求。一些基本的使用者驗證可以放在網關上來做,比如使用者是否已登入,使用者請求中的 token 是否合法等。但是,我們需要權衡一下,網關是否需要校驗使用者的輸入。因為這樣一來,網關就需要從隻關心協定頭,到需要關心協定體。而協定體中的東西一方面不像協定頭是标準的,另一方面解析協定體還要耗費大量的運作時間,進而降低網關的性能。對此,我想說的是,看具體需求,一方面如果協定體是标準的,那麼可以幹;另一方面,對于解析協定所帶來的性能問題,需要做相應的隔離。
  3. 檢測異常通路。網關需要檢測一些異常通路,比如,在一段比較短的時間内請求次數超過一定數值;還比如,同一用戶端的 4xx 請求出錯率太高……對于這樣的一些請求通路,網關一方面要把這樣的請求屏蔽掉,另一方面需要發出警告,有可能會是一些比較重大的安全問題,如被黑客攻擊。

流量網關

流量網關,顧名思義就是控制流量進入叢集的網關,有很多工作需要在這一步做,對于一個服務叢集,勢必有很多非法的請求或者無效的請求,這時候要将請求拒之門外,降低叢集的流量壓力。

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

定義全局性的、跟具體的後端業務應用和服務完全無關的政策網關就是上圖所示的架構模型——流量網關。流量網關通常隻專注于全局的Api管理政策,比如全局流量監控、日志記錄、全局限流、黑白名單控制、接入請求到業務系統的負載均衡等,有點類似防火牆。Kong 就是典型的流量網關。

下面是kong的架構圖,來自官網:​​https://konghq.com/​​

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

這裡需要補充一點的是,業務網關一般部署在流量網關之後、業務系統之前,比流量網關更靠近業務系統。通常API網指的是業務網關。 有時候我們也會模糊流量網關和業務網關,讓一個網關承擔所有的工作,是以這兩者之間并沒有嚴格的界線。

業務網關

當一個單體應用被拆分成許許多多的微服務應用後,也帶來了一些問題。一些與業務非強相關的功能,比如權限控制、日志輸出、資料加密、熔斷限流等,每個微服務應用都需要,是以存在着大量重複的代碼實作。而且由于系統的疊代、人員的更替,各個微服務中這些功能的實作細節出現了較大的差異,導緻維護成本變高。另一方面,原先單體應用下非常容易做的接口管理,在服務拆分後沒有了一個集中管理的地方,無法統計已存在哪些接口、接口定義是什麼、運作狀态如何。

網關就是為了解決上述問題。作為微服務體系中的核心基礎設施,一般需要具備接口管理、協定适配、熔斷限流、安全防護等功能,各種開源的網關産品(比如 zuul)都提供了優秀高可擴充性的架構、可以很友善的實作我們需要的一些功能、比如鑒權、日志監控、熔斷限流等。

與流量網關相對應的就是業務網關,業務網關更靠近我們的業務,也就是與伺服器應用層打交道,那麼有很多應用層需要考慮的事情就可以依托業務網關,例如線上程模型、協定适配、熔斷限流,服務編排等。下面看看業務網關體系結構:

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

圖檔來自業務網關的落地實踐:

從這個途中可以看出業務網關主要職責以及所做的事情, 目前業務網關比較成熟的 API 網關架構産品有三個 分别是:Zuul1、Zuul2 和 SpringCloud Gateway, 後面再進行對比。

常見網關對比

既然對比,就先宏觀上對各種網關有一個了解,後面再挑一些常用的或者說應用廣泛的詳細了解。

目前常見的開源網關大緻上按照語言分類有如下幾類:

  • Nginx+lua:OpenResty、Kong、Orange、Abtesting gateway 等
  • Java:Zuul/Zuul2、Spring Cloud Gateway、Kaazing KWG、gravitee、Dromara soul 等
  • Go:Janus、fagongzi、Grpc-gateway
  • Dotnet:Ocelot
  • NodeJS:Express Gateway、Micro Gateway

按照使用數量、成熟度等來劃分,主流的有 4 個:

  • OpenResty
  • Kong
  • Zuul/Zuul2
  • Spring Cloud Gateway

OpenResty

OpenResty是一個流量網關,根據前面對流量網關的介紹就可以知道流量網關的指責。

OpenResty基于 Nginx 與 Lua 的高性能 Web 平台,其内部內建了大量精良的 Lua 庫、第三方子產品以及大多數的依賴項。用于友善地搭建能夠處理超高并發、擴充性極高的動态 Web 應用、Web 服務和動态網關。

通過揉和衆多設計良好的 Nginx 子產品,OpenResty 有效地把 Nginx 伺服器轉變為一個強大的 Web 應用伺服器,基于它開發人員可以使用 Lua 程式設計語言對 Nginx 核心以及現有的各種 Nginx C 子產品進行腳本程式設計,建構出可以處理一萬以上并發請求的極端高性能的 Web 應用

OpenResty 最早是順應 OpenAPI 的潮流做的,是以 Open 取自“開放”之意,而Resty便是 REST 風格的意思。雖然後來也可以基于 ngx_openresty 實作任何形式的 web service 或者傳統的 web 應用。

也就是說 Nginx 不再是一個簡單的靜态網頁伺服器,也不再是一個簡單的反向代理了。第二代的 openresty 緻力于通過一系列 nginx 子產品,把nginx擴充為全功能的 web 應用伺服器。

ngx_openresty 是使用者驅動的項目,後來也有不少國内使用者的參與,從 openresty.org 的點選量分布上看,國内和國外的點選量基本持平。

ngx_openresty 目前有兩大應用目标:

  1. 通用目的的 web 應用伺服器。在這個目标下,現有的 web 應用技術都可以算是和 OpenResty 或多或少有些類似,比如 Nodejs, PHP 等等。ngx_openresty 的性能(包括記憶體使用和 CPU 效率)算是最大的賣點之一。
  2. Nginx 的腳本擴充程式設計,用于建構靈活的 Web 應用網關和 Web 應用防火牆。有些類似的是 NetScaler。其優勢在于 Lua 程式設計帶來的巨大靈活性。

Kong

Kong基于OpenResty開發,也是流量層網關, 是一個雲原生、快速、可擴充、分布式的Api 網關。繼承了OpenResty的高性能、易擴充性等特點。Kong通過簡單的增加機器節點,可以很容易的水準擴充。同時功能插件化,可通過插件來擴充其能力。而且在任何基礎架構上都可以運作。具有以下特性:

  • 提供了多樣化的認證層來保護Api。
  • 可對出入流量進行管制。
  • 提供了可視化的流量檢查、監視分析Api。
  • 能夠及時的轉換請求和相應。
  • 提供log解決方案
  • 可通過api調用Serverless 函數。

Kong解決了什麼問題

當我們決定對應用進行微服務改造時,應用用戶端如何與微服務互動的問題也随之而來,畢竟服務數量的增加會直接導緻部署授權、負載均衡、通信管理、分析和改變的難度增加。

面對以上問題,API GATEWAY是一個不錯的解決方案,其所提供的通路限制、安全、流量控制、分析監控、日志、請求轉發、合成和協定轉換功能,可以解放開發者去把精力集中在具體邏輯的代碼,而不是把時間花費在考慮如何解決應用和其他微服務連結的問題上。

圖檔來自Kong官網:

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

可以看到Kong解決的問題。專注于全局的Api管理政策,全局流量監控、日志記錄、全局限流、黑白名單控制、接入請求到業務系統的負載均衡等。

Kong的優點以及性能

在衆多 API GATEWAY 架構中,Mashape 開源的高性能高可用API網關和API服務管理層——KONG(基于 NGINX+Lua)特點尤為突出,它可以通過插件擴充已有功能,這些插件(使用 lua 編寫)在API請求響應循環的生命周期中被執行。于此同時,KONG本身提供包括 HTTP 基本認證、密鑰認證、CORS、TCP、UDP、檔案日志、API請求限流、請求轉發及 NGINX 監控等基本功能。目前,Kong 在 Mashape 管理了超過 15,000 個 API,為 200,000 開發者提供了每月數十億的請求支援。

Kong架構

Kong提供一些列的服務,這就不得不談談内部的架構:

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

首先最底層是基于Nginx, Nginx是高性能的基礎層, 一個良好的負載均衡、反向代理器,然後在此基礎上增加Lua腳本庫,形成了OpenResty,攔截請求, 響應生命周期,可以通過Lua編寫腳本,是以插件比較豐富。

Zuul1.0

Zuul是所有從裝置和web站點到Netflix流媒體應用程式後端請求的前門。作為一個邊緣服務應用程式,Zuul被建構來支援動态路由、監視、彈性和安全性。它還可以根據需要将請求路由到多個Amazon自動伸縮組。

Zuul使用了一系列不同類型的過濾器,使我們能夠快速靈活地将功能應用到服務中。

過濾器

過濾器是Zuul的核心功能。它們負責應用程式的業務邏輯,可以執行各種任務。

  • Type: 通常定義過濾器應用在哪個階段
  • Async: 定義過濾器是同步還是異步
  • Execution Order: 執行順序
  • Criteria: 過濾器執行的條件
  • Action: 如果條件滿足,過濾器執行的動作

Zuul提供了一個動态讀取、編譯和運作這些過濾器的架構。過濾器之間不直接通信,而是通過每個請求特有的RequestContext共享狀态。

下面是Zuul的一些過濾器:

Incoming

Incoming過濾器在請求被代理到Origin之前執行。這通常是執行大部分業務邏輯的地方。例如:認證、動态路由、速率限制、DDoS保護、名額。

Endpoint

Endpoint過濾器負責基于incoming過濾器的執行來處理請求。Zuul有一個内置的過濾器(ProxyEndpoint),用于将請求代理到後端伺服器,是以這些過濾器的典型用途是用于靜态端點。例如:健康檢查響應,靜态錯誤響應,404響應。

Outgoing

Outgoing過濾器在從後端接收到響應以後執行處理操作。通常情況下,它們更多地用于形成響應和添加名額,而不是用于任何繁重的工作。例如:存儲統計資訊、添加/剝離标準标題、向實時流發送事件、gziping響應。

過濾器類型

下面是與一個請求典型的生命周期對應的标準的過濾器類型:

  • PRE: 路由到Origin之前執行
  • ROUTING: 路由到Origin期間執行
  • POST: 請求被路由到Origin之後執行
  • ERROR: 發生錯誤的時候執行

這些過濾器幫助我們執行以下功能:

  • 身份驗證和安全性: 識别每個資源的身份驗證需求,并拒絕不滿足它們的請求
  • 監控: 在邊緣跟蹤有意義的資料和統計資料,以便給我們一個準确的生産視圖
  • 動态路由: 動态路由請求到不同的後端叢集
  • 壓力測試: 逐漸增加叢集的流量,以評估性能
  • 限流: 為每種請求類型配置設定容量,并丢棄超過限制的請求
  • 靜态響應處理: 直接在邊緣建構一些響應,而不是将它們轉發到内部叢集

Zuul 1.0 請求生命周期

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

Netflix宣布了通用API網關Zuul的架構轉型。Zuul原本采用同步阻塞架構,轉型後叫作Zuul2,采用異步非阻塞架構。Zuul2和Zuul1在架構方面的主要差別在于,Zuul2運作在異步非阻塞的架構上,比如Netty。Zuul1依賴多線程來支援吞吐量的增長,而Zuul 2使用的Netty架構依賴事件循環和回調函數。

Zuul2.0

Zuul 2.0 架構圖

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

上圖是Zuul2的架構,和Zuul1沒有本質差別,兩點變化:

  1. 前端用Netty Server代替Servlet,目的是支援前端異步。後端用Netty Client代替Http Client,目的是支援後端異步。
  2. 過濾器換了一下名字,用Inbound Filters代替Pre-routing Filters,用Endpoint Filter代替Routing Filter,用Outbound Filters代替Post-routing Filters。

Inbound Filters : 路由到 Origin 之前執行,可以用于身份驗證、路由和裝飾請求

Endpoint Filters : 可用于傳回靜态響應,否則内置的ProxyEndpoint過濾器将請求路由到Origin

Outbound Filters : 從Origin那裡擷取響應後執行,可以用于度量、裝飾使用者的響應或添加自定義header

有兩種類型的過濾器:sync 和 async。因為Zuul是運作在一個事件循環之上的,是以從來不要在過濾中阻塞。如果你非要阻塞,可以在一個異步過濾器中這樣做,并且在一個單獨的線程池上運作,否則可以使用同步過濾器。

上文提到過Zuul2開始采用了異步模型

優勢是異步非阻塞模式啟動的線程很少,基本上一個CPU core上隻需啟一個事件環處理線程,它使用的線程資源就很少,上下文切換(Context Switch)開銷也少。非阻塞模式可以接受的連接配接數大大增加,可以簡單了解為請求來了隻需要進隊列,這個隊列的容量可以設得很大,隻要不逾時,隊列中的請求都會被依次處理。

不足,異步模式讓程式設計模型變得複雜。一方面Zuul2本身的代碼要比Zuul1複雜很多,Zuul1的代碼比較容易看懂,Zuul2的代碼看起來就比較費勁。另一方面異步模型沒有一個明确清晰的請求->處理->響應執行流程(call flow),它的流程是通過事件觸發的,請求處理的流程随時可能被切換斷開,内部實作要通過一些關聯id機制才能把整個執行流再串聯起來,這就給開發調試運維引入了很多複雜性,比如你在IDE裡頭調試異步請求流就非常困難。另外ThreadLocal機制在這種異步模式下就不能簡單工作,因為隻有一個事件環線程,不是每個請求一個線程,也就沒有線程局部的概念,是以對于CAT這種依賴于ThreadLocal才能工作的監控工具,調用鍊埋點就不好搞(實際可以工作但需要進行特殊處理)。

總體上,異步非阻塞模式比較适用于IO密集型(IO bound)場景,這種場景下系統大部分時間在處理IO,CPU計算比較輕,少量事件環線程就能處理。

Zuul 與 Zuul 2 性能對比

圖檔來源:​​https://www.slideshare.net/artgon/zuuls-journey-to-nonblocking​​

億級流量架構網關設計思路,常用網關對比,寫得太好了。。

Netflix給出了一個比較模糊的資料,大緻Zuul2的性能比Zuul1好20%左右,這裡的性能主要指每節點每秒處理的請求數。為什麼說模糊呢?因為這個資料受實際測試環境,流量場景模式等衆多因素影響,你很難複現這個測試資料。即便這個20%的性能提升是确實的,其實這個性能提升也并不大,和異步引入的複雜性相比,這20%的提升是否值得是個問題。Netflix本身在其博文22和ppt11中也是有點含糊其詞,甚至自身都有一些疑問的。

Spring Cloud Gateway

SpringCloud Gateway 是 Spring Cloud 的一個全新項目,該項目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技術開發的網關,它旨在為微服務架構提供一種簡單有效的統一的 API 路由管理方式。

Spring Boot 基礎就不介紹了,推薦下這個實戰教程:

​​https://github.com/javastacks/spring-boot-best-practice​​

SpringCloud Gateway 作為 Spring Cloud 生态系統中的網關,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,沒有對新版本的Zuul 2.0以上最新高性能版本進行內建,仍然還是使用的Zuul 2.0之前的非Reactor模式的老版本。而為了提升網關的性能,SpringCloud Gateway是基于WebFlux架構實作的,而WebFlux架構底層則使用了高性能的Reactor模式通信架構Netty。

Spring Cloud Gateway 的目标,不僅提供統一的路由方式,并且基于 Filter 鍊的方式提供了網關基本的功能,例如:安全,監控/名額,和限流。

Spring Cloud Gateway 底層使用了高性能的通信架構Netty。

SpringCloud Gateway 特征

SpringCloud官方,對SpringCloud Gateway 特征介紹如下:

(1)基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0

(2)內建 Hystrix 斷路器

(3)內建 Spring Cloud DiscoveryClient

(4)Predicates 和 Filters 作用于特定路由,易于編寫的 Predicates 和 Filters

(5)具備一些網關的進階功能:動态路由、限流、路徑重寫

從以上的特征來說,和Zuul的特征差别不大。SpringCloud Gateway和Zuul主要的差別,還是在底層的通信架構上。

簡單說明一下上文中的三個術語:

Filter(過濾器)

和Zuul的過濾器在概念上類似,可以使用它攔截和修改請求,并且對上遊的響應,進行二次處理。過濾器為org.springframework.cloud.gateway.filter.GatewayFilter類的執行個體。

Route(路由)

網關配置的基本組成子產品,和Zuul的路由配置子產品類似。一個Route子產品由一個 ID,一個目标 URI,一組斷言和一組過濾器定義。如果斷言為真,則路由比對,目标URI會被通路。

Predicate(斷言):

這是一個 Java 8 的 Predicate,可以使用它來比對來自 HTTP 請求的任何内容,例如 headers 或參數。斷言的輸入類型是一個 ServerWebExchange。

幾種網關的對比

網關 限流 鑒權 監控 易用性 可維護性 成熟度
Spring Cloud Gateway 可以通過IP,使用者,叢集限流,提供了相應的接口進行擴充 普通鑒權、auth2.0 Gateway Metrics Filter 簡單易用 spring系列可擴充強,易配置 可維護性好 spring社群成熟,但gateway資源較少
Zuul2 可以通過配置檔案配置叢集限流和單伺服器限流亦可通過filter實作限流擴充 filter中實作 filter中實作 參考資料較少 可維護性較差 開源不久,資料少
OpenResty 需要lua開發 需要lua開發 需要開發 簡單易用,但是需要進行的lua開發很多 可維護性較差,将來需要維護大量lua腳本 很成熟資料很多
Kong 根據秒,分,時,天,月,年,根據使用者進行限流。可在原碼的基礎上進行開發 普通鑒權,Key Auth鑒權,HMAC,auth2.0 可上報datadog,記錄請求數量,請求資料量,應答資料量,接收于發送的時間間隔,狀态碼數量,kong内運作時間 簡單易用,api轉發通過管理者接口配置,開發需要lua腳本 "可維護性較差,将來需要維護大量lua庫 相對成熟,使用者問題彙總,社群,插件開源

參考:

  • ​​https://www.slideshare.net/artgon/zuuls-journey-to-nonblocking​​
  • ​​https://netflixtechblog.com/zuul-2-the-netflix-journey-to-asynchronous-non-blocking-systems-45947377fb5c​​

覺得不錯,别忘了随手點贊+轉發哦!

繼續閱讀