目標
- 自定義請求入口配置
- WebFlux針對Http請求的核心接口對應Soul的實現(xiàn)
- 請求從客戶端發(fā)起到soul的分析
- 請求到達SoulWebHandler處理大體流程
- 總結
自定義請求入口配置
我們在soul-web模塊中看到SoulConfiguration配置類,其中配置了SoulWebHandler類與DispatcherHandler。之前閱讀過Spring Cloud Gateway 我們知道SCG巧用了Spring Web容器的Http請求入口DispatcherHandler。本來我想soul中為什么要創(chuàng)建兩個實現(xiàn)WebHandler的Bean呢,我就測試:
- 注釋掉DispatcherHandler ,系統(tǒng)正常運行請求正常。
- 注釋掉SoulWebHandler 打開DispatcherHandler ,系統(tǒng)也正常運行,請求這里肯定不行了。因為soul的主要處理邏輯是在soulwebhandler
- 將兩個都注釋掉,系統(tǒng)可以啟動正常。
那我就懷疑只存在SoulWebHandler,為什么還要Dispatcherhandler。后來我就從SpringApplication加載開始 代碼跟蹤,發(fā)現(xiàn)在實例化WebHttpHandlerBuilder 時候系統(tǒng)默認是查找BeanName為webHandler的實例,如果我們沒有自定義的話,那么就默認使用DispatcherHandler。如果自定義Bean定義Name不是webHandler也是沒有用的。
WebFlux針對Http請求的核心接口對應Soul的實現(xiàn)
- ReactiveWebServerFactory - SoulNettyWebServerFactory
不過SoulNettyWebServerFactory 內部也是 實例化了ReactiveWebServerFactory
image
- WebHandler - SoulWebHandler
- WebServer - NettyWebServer
- HttpHandler - HttpWebHandlerAdapter
HttpWebHandlerAdapter 和 HttpServer 和 LifeCycleTimeout 組合成了WebServer,并提交給Servermanager 進行管理
請求從客戶端發(fā)起到soul的分析
首先soul是基于WebFlux實現(xiàn)的,所以請求先到ReactorHttpHandlerAdapter,這是響應式請求的入口也是HttpHandler適配器
- 實例化Request
- 實例化Response
- 根據(jù)soul真正的HttpHandler -> HttpWebHandlerAdapter 進一步處理
這里做的事情就是 根據(jù) ReactorHttpHandlerAdapter 實例化的 Request,Response 創(chuàng)建業(yè)務層使用的exchange,下面就進入WebHandler具體的實體入口Handler,soul中就是SoulWebHandler
請求到達SoulWebHandler處理大體流程
上一篇我們知道的請求怎么進來的,和為什么會這樣進來,這些都是Spring 啟動加載時候按照SpringWeb 容器啟動加載的一些固定化流程配置。只是我們知道這些流程之后,對應的去實現(xiàn)相應的接口,從而達到相應的目的。下面進入請求分析:
- 請求進入SoulWebHandler->Handler,首先使用Metrics 進行監(jiān)控的開始動作,獲取請求處理的開始時間
- 進入默認的DefaultSoulPluginChain處理,并將使用的插件作為參數(shù)傳遞進去
Soul插件調用鏈設計與SCG的Filter調用鏈設計一樣,最初是Spring web 的 WebFilter 設計而來的,SCG中 GlobalFilter 與GatewayFilter 也是仿照這個設計的
image
- execute()執(zhí)行
有人會問插件鏈調用不同的插件,他是按照什么順序執(zhí)行的,在我們初始化WebHandler 時候 ObjectProvider 依賴查找對應的 Plugin ,他們按照 Ordered 進行排序從而決定了執(zhí)行插件的順序流程
- 先判斷當前的執(zhí)行index 是否大于 插件的個數(shù),如果大于則返回一個空的執(zhí)行流。調用鏈直接結束
- 然后根據(jù)index拿對應的插件
- 根據(jù) exchange 作為參數(shù)判斷此插件是否需要執(zhí)行,具體判斷是在具體插件的內部做處理
- 如果需要執(zhí)行則調用execute 根據(jù)具體的插件執(zhí)行流程,決定是否要往下執(zhí)行。
總結
其實本章內容寫的雖然少,但是分析內部的源碼流程卻花費了很多時間。從spring 加載啟動,什么時候初始化Bean 什么時候上下文刷新,如何實例化WebServerManager 等等,都已經(jīng)了解了。其實學東西最底層的東西了解了,了解上層應用就很輕松了。我對于spring 啟動的流程單獨做了腦圖,后續(xù)會放出來。
