Spring Cloud Gateway
Spring Cloud 2.x 實 現(xiàn) 了 社 區(qū) 生 態(tài) 下 的 Spring CloudGateway(簡稱SCG)微服務(wù)網(wǎng)關(guān)項目。Spring Cloud Gateway基于WebFlux框架開發(fā),目標是替換掉Zuul。
Spring Cloud Gateway概述
Spring Cloud Gateway主要有兩個特性:
①非阻塞,默認使用RxNetty作為響應(yīng)式Web容器,通過非阻塞方式,利用較少的線程和資源來處理高并發(fā)請求,并提升服務(wù)資源利用的可伸縮性。
②函數(shù)式編程端點,通過使用Spring WebFlux的函數(shù)式編程模式定義路由端點,處理請求。
Spring Cloud Gateway可與Eureka、Ribbon、Hystrix等組件配合使用,基于Spring 5的Reactor和Spring Boot 2構(gòu)建,使用Netty作為底層通信框架,支持異步非阻塞編程模型和響應(yīng)式編程框架,解決了Zuul框架的I/O阻塞問題和線程收斂問題。使用Spring WebFlux框架可以使Spring Cloud Gateway在高并發(fā)場景下具有更好的性能表現(xiàn),占用更少的資源。
下面是Spring Cloud官方對Spring Cloud Gateway特征的介紹。
● 基于Spring Framework 5、Reactor和Spring Boot 2.0框架。
● 根據(jù)請求的屬性可以匹配對應(yīng)的路由。
● 集成Hystrix。
● 集成Spring Cloud DiscoveryClient。
● 把易于編寫的Predicates和Filters作用于特定路由。
● 具備一些網(wǎng)關(guān)的高級功能,如動態(tài)路由、限流、路徑重寫。
對于微服務(wù)網(wǎng)關(guān)來說,最核心的特征包括路由和過濾器機制。從功能特性上來看,Spring Cloud Gateway和Zuul具備相似的特性。它們都可以集成Hystrix、Ribbon負載均衡及Spring Cloud的現(xiàn)有組件來實現(xiàn)附加功能。而且Spring Cloud Gateway的本質(zhì)特性還體現(xiàn)在底層的通信框架上,它可以基于Netty的I/O多路復(fù)用和事件響應(yīng)機制來實現(xiàn)網(wǎng)絡(luò)通信;它的另外一大特性就是使用Spring Framework 5的響應(yīng)式編程模型,允許通過Spring WebFlux實現(xiàn)異步非阻塞特性,在性能和資源利用率上,都有了質(zhì)的提升。在編程范式上,Spring CloudGateway使用函數(shù)式編程模式。官方提供的Spring Cloud Gateway的架構(gòu)圖如下所示。
Spring Cloud Gateway的核心概念
簡單說明一下架構(gòu)圖中的三個術(shù)語。
● Filter(過濾器):和Zuul的過濾器在概念上類似,可以使用Filter攔截和修改請求,實現(xiàn)對上游的響應(yīng),進行二次處理,實現(xiàn)橫切與應(yīng)用無關(guān)的功能,如安全、訪問超時設(shè)置、限流等功能。
● Route(路由):網(wǎng)關(guān)配置的基本組成模塊,和Zuul的路由配置模塊類似。一個Route模塊由一個ID、一個目標URI、一組斷言和一組過濾器組成。如果斷言為真,則路由匹配,目標URI會被訪問。
● Predicate(斷言):Predicate來自Java 8的接口,它可以用來匹配來自HTTP請求的任何內(nèi)容,例如headers或參數(shù)。接口包含多種默認方法,并將Predicate組合成復(fù)雜的邏輯(與、或、非),可以用于接口參數(shù)校驗、路由轉(zhuǎn)發(fā)判斷等。
Spring Cloud Gateway的接入和配置
Spring Cloud Gateway依賴Spring WebFlux提供的Netty運行時環(huán)境,所以Spring Boot必須是2.0或者以上版本。基本的Spring Cloud環(huán)境配置確認后,主要的接入步驟如下。
1.Maven依賴引入
2.路由配置方式一:配置文件方式
各字段含義如下。
● id:自定義的路由ID,保持唯一。
● uri:目標服務(wù)地址。
● predicates:路由條件,Predicate接受一個輸入?yún)?shù),返回一個布爾值結(jié)果。
○ 第一個Predicate基于URL的方式。配置文件的第一個路由的配置采用URL方式,配置了一個ID為url-proxy-1的URI代 理 規(guī) 則 。 路 由 的 規(guī) 則 為 : 當 訪 問 地 址 為http://localhost:8080/csdn/1.jsp時,會路由到上游地址https://localhost:8010/1.jsp。○ 第二個Predicate基于服務(wù)ID發(fā)現(xiàn)的方式。配置文件的第二個路由的配置采用與注冊中心相結(jié)合的服務(wù)發(fā)現(xiàn)方式,與單個URI的路由配置相比,區(qū)別其實很小,僅在于URI的schema協(xié)議不同。單個URI地址的schema協(xié)議,一般為HTTP或者HTTPs協(xié)議。
3.基于代碼DSL方式的路由配置接入
路由轉(zhuǎn)發(fā)功能同樣可以通過代碼來實現(xiàn),我們可以在啟動類GatewayApplication中添加customRouteLocator方法來定制轉(zhuǎn)發(fā)規(guī)則,代碼如下:
Spring Cloud Gateway的工作原理
客戶端向Spring Cloud Gateway發(fā)出HTTP請求后,如果GatewayHandlerMapping 確 定 請 求 與 路 由 匹 配 , 則 將 其 發(fā) 送 到 GatewayWebHandler。WebHandler通過該請求的特定過濾器鏈處理請求。過濾器 可 以 在 發(fā) 送 代 理 請 求 之 前 或 之 后 執(zhí) 行 邏 輯 。 在 Spring CloudGateway的執(zhí)行流程中,首先執(zhí)行所有“pre filter”邏輯,然后進行回源請求代理。在請求代理執(zhí)行完后,執(zhí)行“post filter”邏輯。在“pre”類型的過濾器中,可以實現(xiàn)參數(shù)校驗、權(quán)限校驗、流量監(jiān)控、日志輸出、協(xié)議轉(zhuǎn)換等功能;在“post”類型的過濾器中,可以實現(xiàn)響應(yīng)內(nèi)容、響應(yīng)頭的修改,日志的輸出、流量監(jiān)控等功能。核心工作流程如下圖所示。
Predicate條件
在Spring Cloud Gateway中,Spring利用Predicate的特性實現(xiàn)了各種路由匹配規(guī)則,通過Header、請求參數(shù)等不同條件來匹配對應(yīng)的路由。
我們來看Spring Cloud Gateway內(nèi)置的幾種Predicate的使用方法。
在上述配置文件中,如果多種Predicates同時存在于同一個路由,請求必須同時滿足所有條件才能被這個路由匹配。當一個請求滿足多個路由的Predicate條件時,請求只會被首個成功匹配的路由轉(zhuǎn)發(fā)。下面分別對不同規(guī)則的路由匹配進行解釋。
● 通過請求路徑匹配(Path Route Predicate)
路由斷言工廠接收一個參數(shù),根據(jù)Path定義好的規(guī)則來判斷訪問的URI是否匹配。配置示例如下:
如果請求路徑符合要求,則此路由將匹配,例如/hello/1或者/hello/world。
使用curl測試,命令行輸入:
經(jīng)過測試發(fā)現(xiàn),第一條和第二條命令可以正常獲取頁面返回值,最后一個命令報404錯誤,證明路由是通過指定路徑來匹配的。
● 通過請求參數(shù)匹配(Query Route Predicate)
路由斷言工廠接收兩個參數(shù):一個必需的參數(shù)和一個可選的正則表達式。配置示例如下:
在這樣的配置中,只要請求中包含helloworld屬性的參數(shù)即可匹配路由。使用curl測試,命令行輸入:
經(jīng)過測試發(fā)現(xiàn),只要請求中帶有helloworld參數(shù)就會匹配路由,不帶helloworld參數(shù)則不會匹配。還可以將Query的值以鍵值對的方式進行配置,這樣在請求時會對屬性值和正則表達式都進行匹配,鍵值對匹配后才會正確執(zhí)行路由邏輯。
在上述路由匹配中,請求中包含hello屬性并且參數(shù)值是以world開頭的、長度為三位的字符串,才會進行匹配和路由。使用curl測試,命令行輸入:
測試可以返回正確的頁面代碼。如果將hello的屬性值改為ok,再次訪問就會報404錯誤,證明路由需要匹配正則表達式才會進行路由。
● 通過請求方法匹配
路由斷言工廠接收一個參數(shù),即需要匹配HTTP方法。通過POST、GET、PUT、DELETE等不同的請求方式來進行路由。
使用curl測試(#curl默認以GET的方式去請求),命令行輸入:
測試返回頁面代碼,證明匹配到路由。
我們再以POST的方式請求測試。
返回404錯誤表示沒有找到,證明沒有匹配上路由。
● 通過Header屬性匹配
路由斷言工廠接收兩個參數(shù),分別是請求頭名稱和正則表達式。
Header Route Predicate和Cookie Route Predicate一樣,也是接收2個參數(shù):一個header的屬性值和一個正則表達式。這個屬性值和正則表達式匹配則執(zhí)行。
● 通過Host路由匹配
Spring Cloud Gateway 可 以 根 據(jù) Host 名 進 行 匹 配 轉(zhuǎn) 發(fā) , HostRoute Predicate接收一組參數(shù)、一組匹配的域名列表。它通過參數(shù)中的主機地址作為匹配規(guī)則。
使用curl測試,命令行輸入:
通過測試以上兩種Host設(shè)置方式,均可匹配到host_route,去掉host參數(shù)則會報404錯誤。
● 時間匹配
Predicate支持設(shè)置時間,在請求轉(zhuǎn)發(fā)時,先判斷這個時間與我們設(shè)置的時間,然后進行轉(zhuǎn)發(fā),所以又細分為設(shè)置時間后斷言、設(shè)置時間前斷言、設(shè)置時間之間斷言。
設(shè)置時間后斷言:從After Route Predicate Factory中獲取一個UTC時間格式的參數(shù),當請求的當前時間在配置的UTC時間之后,則成功匹配,否則不能成功匹配。下面是實例配置:
設(shè)置時間前斷言:從Before Route Predicate Factory中獲取一個UTC時間格式的參數(shù),當請求的當前時間在配置的UTC時間之前,則成功匹配,否則不能成功匹配。下面是實例配置:
設(shè)置時間之間斷言:從Between Route Predicate Factory中獲取一個UTC時間格式的參數(shù),當請求的當前時間在配置的UTC時間之間,則成功匹配,否則不能成功匹配。下面是實例配置:
● 通過Cookie匹配
Cookie路由斷言會取兩個參數(shù),一個是Cookie name,一個是正則表達式,路由規(guī)則是通過獲取的對應(yīng)Cookie name值和正則表達式進行匹配,如果匹配上就會執(zhí)行路由,如果沒有匹配上則不執(zhí)行。
● 通過IP地址匹配
RemoteAddr Route Predicate Factory配置一個IPv4或者IPv6網(wǎng)段的字符串或者IP地址。當請求的IP地址在網(wǎng)段之內(nèi)或者與配置的IP地址相同,匹配成功,則進行轉(zhuǎn)發(fā),否則不進行轉(zhuǎn)發(fā)。
可以將curl localhost:8080設(shè)置為本機的IP地址進行測試,如果請求的遠程地址是192.168.1.30,則此路由將匹配。
GatewayFilter與GlobalFilter
Spring Cloud Gateway 中 有 兩 種 Filter , 一 種 是GlobalFilter(全局過濾器),一種是GatewayFilter。GlobalFilter默認對所有路由有效,GatewayFilter需要通過路由分組指定。
GlobalFilter接口與GatewayFilter具有相同的簽名,是有條件地應(yīng)用于所有路由的特殊過濾器。
當請求進入路由匹配邏輯時,Web Handler會將GlobalFilter的所有實例和所有GatewayFilter路由特定實例添加到Filter Chain組件。Filter組合執(zhí)行的順序由Ordered接口決定,可以通過getOrder方法或使用@Order注釋來設(shè)置。Spring Cloud Gateway通過執(zhí)行過濾器將邏輯分為“前置”和“后置”階段,優(yōu)先級較高的前置過濾器會優(yōu)先被執(zhí)行,而優(yōu)先級較高的后置過濾器的執(zhí)行順序正好相反,最后執(zhí)行。
GatewayFilter Factories
過濾器允許以某種方式修改傳入的HTTP請求或返回的HTTP響應(yīng)。
過濾器的作用域是某些特定路由。Spring Cloud Gateway包括許多內(nèi)置的過濾器工廠。
● 實現(xiàn)前綴修改(增加前綴、去掉前綴)
PrefixPathGatewayFilterFactory及StripPrefixGatewayFilterFactory 是 一 對 處 理 請 求 URL 的 前 綴 的Filter工廠,前者添加前綴,后者去除前綴。
配置文件application.yml如下:
○
PrefixPathGatewayFilterFactory允許你在對應(yīng)的路由請求前增加前綴。例如實例配置中的請求/hello,最后轉(zhuǎn)發(fā)到目標服務(wù)的路徑變?yōu)?mypath/hello。
○
StripPrefixGatewayFilterFactory允許你在對應(yīng)的路由請求前去除前綴,例如實例配置中的請求/name/bar/foo,去除前面兩個前綴后,最后轉(zhuǎn)發(fā)到目標服務(wù)的路徑為/foo。
● 實現(xiàn)請求頭內(nèi)容添加和改寫
AddRequestHeader GatewayFilter Factory采用一對名稱和值作為參數(shù),配置文件application.yml如下:
對于所有匹配的請求,將在向下游請求的頭內(nèi)容中添加x?request-foo:bar header。
● 實現(xiàn)請求體內(nèi)容添加和改寫
AddRequestParameter GatewayFilter Factory采用一對名稱和值作為參數(shù),配置參數(shù)application.yml如下:
對于所有匹配的請求,將向下游請求添加foo=bar查詢字符串。
● 實現(xiàn)熔斷降級
Hystrix GatewayFilter允許向網(wǎng)關(guān)路由引入Hystrix,保護服務(wù)不受級聯(lián)故障的影響,并允許在下游故障時提供fallback響應(yīng)。要在項 目 中 啟 用 Hystrix 網(wǎng) 關(guān) 過 濾 器 , 需 要 向 Hystrix 的 依 賴 HystrixGatewayFilter Factory添加一個name參數(shù),即HystrixCommand的名稱,配置文件application.yml如下:
當調(diào)用hystrixfallback時,將轉(zhuǎn)發(fā)到/incaseoffailureusethis。注意,這個示例還演示了通過目標URI上的“l(fā)b”前綴使Spring Cloud Netflix Ribbon客戶端實現(xiàn)負載均衡。主要場景是網(wǎng)關(guān)應(yīng)用程序中的內(nèi)部控制器或處理程序使用fallbackUri,它也可以將請求重新路由到外部應(yīng)用程序中的控制器或處理程序。
● 分布式限流
SpringCloudGateway內(nèi)置的
RequestRateLimiterGatewayFilterFactory提供限流的能力,基于令牌桶算法實現(xiàn)。目前它內(nèi)置的RedisRateLimiter,依賴Redis來存儲限流配置和統(tǒng)計數(shù)據(jù)。當然你也可以實現(xiàn)自己的RateLimiter,只需實現(xiàn)Spring Cloud Gateway 自 帶 的 RateLimiter 接 口 或 者 繼 承AbstractRateLimiter。
首先,添加Maven依賴。
其次,添加限流配置。
最后,完成對Path的KeyResolver(可以通過KeyResolver來指定限流的Key),實現(xiàn)對特定Path下的限流控制配置。在過濾器中可以配置一個可選的KeyResolver,KeyResolver在配置中根據(jù)名稱使用SpEL引用Bean。#{@myKeyResolver}是引用名為“pathKeyResolver”的Bean的SpEL表達式。KeyResolver接口允許使用可插拔策略來派生限制請求的Key。代碼如下:
Spring Cloud Gateway的動態(tài)路由
下面介紹基于Spring Cloud Gateway的動態(tài)路由實現(xiàn)(相關(guān)代碼將會隨書附帶),實現(xiàn)方式與Zuul的動態(tài)路由實現(xiàn)方式類似,具有比Zuul更加靈活的路由策略和匹配模式。這兩種解決方案如下。
●通過SpringCloudGateway提供的
GatewayControllerEndpointduan端點功能,實現(xiàn)路由的增刪改 查 , 或 者 自 己 實 現(xiàn) ApplicationEventPublisherAware 接口,實現(xiàn)自定義的路由操作方法。具體可以參考源碼:GatewayControllerEndpointduan類。
● 通過實現(xiàn)RouteDefinitionRepository接口,實現(xiàn)自定義的Repository類,實現(xiàn)從數(shù)據(jù)庫或者緩存中動態(tài)加載路由信息的功能。架構(gòu)模式與Zuul的動態(tài)路由采用相似的路由加載策略,架構(gòu)流程圖如下。
動態(tài)路由思路及解決方案具體如下。
首先,Admin作為前端管理界面,將用戶對路由的添加、修改等操作通過RouteAsynchService存儲到DB中。DB中的存儲結(jié)構(gòu)如下圖所示。
字段映射關(guān)系如下。
● routeid:標識路由的唯一ID,可以根據(jù)路由ID查找路由,路由ID不能重復(fù)。
● routename:應(yīng)用名稱是標識路由的別名,是非必選項。
● routeorder:對應(yīng)RouteDefinition中的order屬性。
● routestatus:路由狀態(tài),包括編輯、發(fā)布、下線等狀態(tài)。
● strategy:路由策略,和Zuul的路由策略相似,也支持ServiceID策略和URL策略。
●predicates:對應(yīng)RouteDefinition中的List<PredicateDefinition> predicates策略集合,以鍵值對的形式對應(yīng)斷言策略。
● filters:對應(yīng)RouteDefinition中的List<FilterDefinition>filters集合,以鍵值對的形式對應(yīng)過濾器策略。
● uri:對應(yīng)后端服務(wù),可以是后端服務(wù)的ServiceID,也可以是服務(wù)的URL地址,與路由策略對應(yīng)。
● groupname:標識這個新建的路由歸屬在哪個網(wǎng)關(guān)集群下面。
其次,Spring Cloud Gateway的動態(tài)路由管理策略都通過Admin接收對網(wǎng)關(guān)路由的增刪改查命令,然后通過RouteAsynchService將路由更新服務(wù)并發(fā)布到對應(yīng)的網(wǎng)關(guān)節(jié)點,網(wǎng)關(guān)節(jié)點從數(shù)據(jù)庫動態(tài)獲得最新的路由狀態(tài),更新緩存和當前路由。下面對網(wǎng)關(guān)節(jié)點的事件監(jiān)聽機制進行講解。
說明1#:在代碼段中,refreshRoute方法是事件監(jiān)聽的入口方法,該方法會向Admin管理服務(wù)暴露一個REST服務(wù)。當Admin對路由進行更改后,會調(diào)用refreshRoute方法,觸發(fā)Spring Cloud Gateway自帶的RefreshRoutesEvent事件,同時設(shè)置原子布爾變量routedefine為true,在下面的動態(tài)路由加載中根據(jù)該原子布爾變量決定是從數(shù)據(jù)庫中讀取路由還是從緩存中讀取路由。
下面是定制化的核心路由動態(tài)加載和緩存管理的關(guān)鍵代碼,主要通過實現(xiàn)自定義的路由Repository加載類來動態(tài)地加載路由,通過繼承RouteDefinitionRepository父類來提供路由的配置信息,實現(xiàn)邏輯如下:
說明2#:在代碼段中,
SagRouteDefinationRepository是自定義的路由加載實現(xiàn)類,這個類實現(xiàn)了RouteDefinitionRepository接口。
該接口的源碼如下:
然 后, 跟 進 getRouteDefinitions 方 法, 它是
RouteDefinitionRouteLocator的回調(diào)方法,可以實時更新路由信息,代碼如下:
從源碼中調(diào)用鏈路追溯,可以發(fā)現(xiàn)下面的調(diào)用鏈路:
說明3#:在代碼段中,refreshNeed()方法是判斷緩存是否失效的標識原子布爾變量,當Admin回調(diào)1#代碼段中的刷新接口時,會將該失效接口打開。在路由加載時,如果refreshNeed為false并且routeDefinitions不為空,那么優(yōu)先加載緩存中的路由信息。如果refreshNeed為true,那么優(yōu)先執(zhí)行加載數(shù)據(jù)庫的操作,通過這段代碼的邏輯處理就可以保證網(wǎng)關(guān)中路由的刷新效率和緩存與數(shù)據(jù)庫中路由信息的同步。
說 明 4 # : 該 代 碼 段 是 從 數(shù) 據(jù) 庫 中 加 載 路 由 的 核 心 實 現(xiàn) 。
localteRoutefromDB ( ) 方 法 從 數(shù) 據(jù) 庫 中 加 載 路 由 , 返 回RouteDefinitionVo模型的數(shù)據(jù)庫路由列表信息。下面是該模型類的代碼:
transfer( ) 方 法 實 現(xiàn) 了 從 RouteDefinitionVo 到RouteDefinition的類型轉(zhuǎn)換,下面是transfer()方法調(diào)用的類型轉(zhuǎn)換的核心代碼:
說明5#:在代碼段中,
GatewayPredicateDefinitionFactory完成斷言的模式匹配轉(zhuǎn)換。Predicate-Definition是斷言的模型定義,定義name為Key、args為Value。舉例如下:
GatewayPredicateDefinitionFactory完成過濾器的模式匹配轉(zhuǎn)換。FilterDefinition是過濾器的模型定義,定義name為Key、args為Value。舉例如下:
Spring Cloud Gateway源碼解析
啟動Spring Cloud Gateway,需要依賴官方的Starter組件。下面我們從Maven依賴開始,對Spring Cloud Gateway的源碼進行解析。
初始化加載
上述是
spring-cloud-starter-gateway啟動前需要引用的一個自動配置Starter,可以通過查詢該Starter的源碼發(fā)現(xiàn)Spring CloudGateway的實現(xiàn)所依賴的組件,Maven配置如下:
可 以 看 到 Spring Cloud Gateway 的 Starter 啟 動 類 主 要 依 賴spring-cloud-gateway-core組件。使用EnableAutoConfiguration注解完成自動配置初始化信息,我們在Spring Cloud Gateway下的spring.factories(在包spring-cloud-gateway-core)聲明文件如下:
GatewayAutoConfiguration
說明:
GatewayAutoConfiguration配置是Spring Cloud Gateway的核心配置類,初始化如下組件:
● NettyConfiguration
●GlobalFilter(
AdaptCachedBodyGlobalFilter、RouteToRequestUrlFilter、 ForwardRoutingFilter、ForwardPathFilter、WebsocketRoutingFilter、WeightCalculatorWebFilter等)
● FilteringWebHandler
● GatewayProperties
● PrefixPathGatewayFilterFactory
● RoutePredicateFactory
● RouteDefinitionLocator● RouteLocator
●
RoutePredicateHandlerMapping(查找匹配到的Route并進行處理)
● GatewayWebfluxEndpoint(管理網(wǎng)關(guān)的HTTP API)
HTTP請求路由源碼分析
Spring Cloud Gateway中使用HandlerMapping對請求的鏈接進行解析,匹配對應(yīng)的Route,轉(zhuǎn)發(fā)到對應(yīng)的服務(wù)。下圖為整個請求的流程 , 用 戶 請 求 先 通 過 DispatcherHandler 找 到 對 應(yīng) 的GatewayHandlerMapping,再通過GatewayHandlerMapping解析匹配到的Handler;Handler處理完后,經(jīng)過Filter處理,最終將請求轉(zhuǎn)發(fā)到后端服務(wù)。
在前面的動態(tài)路由加載過程中,其實已經(jīng)貫穿了整個HTTP請求的調(diào)用鏈路,具體如下:
請求先由DispatcherHandler進行處理,DispatcherHandler在初始化時會在Spring IoC容器中查找實現(xiàn)HandlerMapping接口的實現(xiàn)類 。 然 后 保 存 到 內(nèi) 部 變 量 handlerMappings 數(shù) 據(jù) 結(jié) 構(gòu) 中 。
DispatcherHandler 調(diào) 用 handler 方 法 迭 代 handlerMappings 中 的HandlerMapping接口,主要源碼如下:
AbstractHandlerMapping 在 getHandler 方 法 中 封 裝 了CORS(Cross-Origin Resource Sharing,跨域資源共享)。因為所有Handler都可能涉及CORS的處理,所以抽象類AbstractHandlerMapping提供了getHandlerInternal子類來實現(xiàn)查找Handler的具體方法。
RoutePredicateHandlerMapping用于匹配具體的路由,并返回FilteringWebHandler 。 通 過 RoutePredicateHandlerMapping 中 的RouteLocator 對 象 存 儲 啟 動 時 加 載 的 路 由 對 象 信 息 。 當RoutePredicateHandlerMapping獲取對應(yīng)的路由時,會將Route信息存儲到ServerWebExchanges屬性中,然后返回實現(xiàn)了WebHandler接口的FilteringWebHandler 。 FilteringWebHandler 是 一 個 存 放 過 濾 器 的Handler。
調(diào)用
RoutePredicateHandlerMapping的getHandlerInternal方法從RouteLocator獲取路由,并存放在ServerWebExchange中,返回webFilter對象,代碼如下:
DispatcherHandler 通 過 SimpleHandlerAdapter 組 件 調(diào) 用FilteringWebHandler模塊的handler方法,F(xiàn)ilteringWebHandler模塊接 著 調(diào) 用 之 前 在 容 器 中 注 冊 的 所 有 Filter , 處 理 完 畢 后 返 回Response,代碼如下:
小結(jié)
構(gòu)建響應(yīng)式微服務(wù)可以獲得異步、響應(yīng)性、彈性、快速恢復(fù)、背壓等系統(tǒng)特性,同時響應(yīng)式微服務(wù)架構(gòu)在資源占用、高并發(fā)、高吞吐、異步處理場景中具有更強的優(yōu)勢。目前響應(yīng)式框架技術(shù)選型眾多,如果將響應(yīng)式編程應(yīng)用到大規(guī)模生產(chǎn)系統(tǒng)中,則需要進行周密的調(diào)研,并對實際項目周期、人員經(jīng)驗、技術(shù)框架等因素進行綜合權(quán)衡考慮,避免技術(shù)的復(fù)雜度問題成為業(yè)務(wù)發(fā)展過程中的瓶頸。