最近公司要引入統一網關,自己也參與調研了幾種,當在研究Netflix的Zuul2和SpringCloudGateway時被網絡上雜七雜八的材料跟震驚了,不客氣地說很多國內博客都是在誤人子弟,充斥着那些基於SpringCloud全家桶號稱自己使用的是zuul2的“專家”。所以下定決心用一個系列好好介紹下第二代NIO的兩個網關:SpringCloudGateway和NetflixZuul2。
背景介紹
我們系統架構面臨現狀和痛點
1. 流量調度不靈活,完全依賴DNS
雖然後端服務已經實現了多雲多活,但是每次做流量割接的時候都要從DNS層一個運營商一個運營商的一點點的做調度。我需要有個統一接入層,可以直接把一個雲平臺的所有流量直接調到另一個雲平臺上
2. 各IDC的LB組件不同,配置管理不統一
對接入層的配置,變成了對每個產品LB入口的配置,我們大約有近百個應用,而且每個應用又涉及到物理機房IDC、阿里雲、騰訊雲這樣的差異性,而且每家雲平臺LB的設計和操作又千差萬別,所以接入層的配置變成了臃腫而且學習成本很高的一件事情。
3. 突發流量導致雪崩,無限流
公司目前沒有限流策略,今年春節後因爲疫情原因大家都窩在家裏,我們的爆款節目就引發了兩次因流量洪峯導致的重大故障。雖然後端的服務已經具備了很出色的彈性能力,但是彈性畢竟需要時間,因爲缺乏接入層限流的保護,很容易造成後端服務雪崩效應。
4. 無法干預路由策略,無法混沌工程
今年我們將會啓動混沌工程,更需要一個優秀的網關來配合打標或自定義路由,而且要能很好地控制網關的生命週期,因爲混沌工程執行是臨時性的,混沌結束後需要恢復。
我期望中的統一網關應該具備的能力
1、七層轉發:基於path、host、uid、其他自定義方式。
2、攔截策略:統一安全,request、response報文干預。
3、統一管理:統一的監控、日誌、配置管理方案。
4、限流熔斷:基於不同粒度的限流規則。
現狀圖
理想圖
網關發展史
選擇網關之前我們要先了解下netflix與spring的恩怨情仇
蜜月期
2013: Netflix推出以zuul1爲代表開的源項目
2014: SpringBoot誕生,引入Netflix開源組件
2015: SpringCloud誕生,引入Netflix開源組件
2016: 發現Zuul1存在性能問題,Netflix官宣進行優化
爭執期
2016-2017: Netflix跳票
2018-05: Netflix發佈Zuul 2.x,Spring未引入
2018-06: Netflix宣告Eureka 2.0 開源工作停止
分手
2018-11: Netflix宣告Hystrix開源工作停止
2018-11: Spring推出新一代網關Gateway、一些列孵化項目
2018-12:Spring官方宣佈Netflix的相關項目進入維護模式
2018-12::Netflix 宣佈 Spring 系列技術棧進入維護模式
SpringCloud因分手受影響的模塊
spring-cloud-netflix-archaius
spring-cloud-netflix-hystrix-contract
spring-cloud-netflix-hystrix-dashboard
spring-cloud-netflix-hystrix-stream
spring-cloud-netflix-hystrix
spring-cloud-netflix-ribbon
spring-cloud-netflix-turbine-stream
spring-cloud-netflix-turbine
spring-cloud-netflix-zuul
總之一句話:愛過。
網關的發展經歷了BIO和NIO時代
一代網關:BIO
實現方式
基於Thread方式,當I/O阻塞系統,但CPU空閒的時候,可以利用多線程使用CPU資源
性能
嚴重依賴於線程,線程的創建和銷燬成本很高;
線程本身佔用較大內存。
代表
SpringCloudZuul(Netflix-Zuul1)
二代網關:NIO
實現方式
基於Reactor方式,成熟框架(Netty、MINA),當I/O阻塞系統,但CPU空閒的時候,可以利用多線程使用CPU資源。
性能
除了事件的輪詢是阻塞的,剩餘的都是純CPU操作,單線程處理多任務;
由於線程的節約,高鏈接場景下線程切換帶來的問題也隨之解決;
I/O多路複用。
代表
SpringCloudGateway & Netflix-Zuul2
核心網關詳解
Zuul2-架構
基於Filter的體系
Inbound
輸入過濾器,在請求被代理之前執行。可用於:認證、路由、Ddos、指標統計等。
Endpoint
基於輸入過濾器的執行情況處理請求,如:將請求代理到後端等。
Outbound
輸出過濾器處理接收到後端服務返回後的操作;如:增刪響應頭信息、壓縮等
Zuul2-動態過濾器
核心代碼:ZuulFiltersModule,FilterFileManager,FilterLoader
核心配置:zuul.filters.classes,zuul.filters.packages,zuul.filters.locations
SpringCloudGateway
Gateway Handler Mapping
找到與請求相匹配的路由,將其發送到 Gateway Web Handler
Gateway Web Handler
通過指定的過濾器鏈來將請求發送到我們實際的服務執行業務邏輯。
Filter
pre:Gateway轉發請求之前
post:Gateway轉發請求之後
網關對比與選型
網關對比
名稱 |
Zuul1 |
Zuul2 |
Spring Cloud Gateway |
Path注入 |
不自帶,部分可實現 |
不自帶,可以自己實現 |
自帶 |
host轉發 |
不支持 |
不自帶,可以自己實現 |
自帶 |
動態代碼 |
不支持 |
可動態通過代碼修改filter |
不支持 |
動態配置 |
Archaius,Spring |
Netflix Archaius |
Spring(config+bus+actuator)或自開發 |
網關高可用 |
雲平臺的LB+彈性,Eureka |
雲平臺的LB+彈性,Eureka |
雲平臺的LB+彈性,Eureka |
服務發現 |
eureka |
eureka |
eureka,nacos |
功能擴展 |
只擴展過濾器 |
可創建路由規則,過濾規則 |
路由規則,過濾規則都可擴展 |
限流 |
信號量、線程數 |
內置限流統計,需要自己封裝實現,集羣可能需要自開發 |
引入redis計數,可細化到針對IP做限流,限流規則可自定義 |
熔斷 |
Hystrix降級 |
需要基於內置的統計做封裝 |
利用Hystrix |
實現方式 |
BIO |
NIO |
NIO |
技術選型
性能:
Gateway和Zuul2底層都是reactor模式,性能上比zuul1時代提高很多,所以zuul1不考慮。
開源:
Gateway社區更成熟,內置10種路由和20種過濾器,zuul2只有Netflix博客和github可獲取相關資料,很多功能需要自己開發。
特性:
Zuul2基於groovy的filter代碼動態更新是一大亮點,而且與混沌工程配合的天衣無縫,從Zuul2的設計思想來看就是要利用代碼來替代配置。
語言:
Netflix是Java+Groovy體系,Spring是Java體系
總結: 傾向於Zuul2