springcloud gateway 源码解析、请求响应流程、第三方响应结果在 gateway 的经过
大家好,我是烤鴨:
1.? 官方介紹
官方文檔:
看的是 2.2.5.RELEASE?版本的
https://docs.spring.io/spring-cloud-gateway/docs/2.2.5.RELEASE/reference/html/
看一下官方這段說明,gateway 使用的是 webflux 和 reactor,有一些同步的包(data,security 可能不支持)。
還有就是需要netty作為服務器,傳統的 servlet 模型和 war 包不支持。
工作流程:
簡單說就是網關收到客戶端的 request 之后經過一系列請求過濾器到代理的服務,收到 response之后,再經過一系列的響應過濾器返回到網關->客戶端。
2.? 源碼分析
2.1? reactor 介紹
由于 gateway 是基于 reactor 的,先看下 reactor 的 Flux 和 Mono
reactor 是響應式編程,相對的傳統模式 遍歷-> 拉取 ->TODO ,而響應式 遍歷(發布) -> 訂閱者 -> TODO,是基于 發布 —?訂閱的模式。
而 Flux 和 Mono 是 Reactor 中的兩個基本概念。都實現 CorePublisher 接口。(用于發布的元素)
Flux 表示的是包含 0 到 N 個元素的異步序列。在該序列中可以包含三種不同類型的消息通知:正常的包含元素的消息、序列結束的消息和序列出錯的消息。當消息通知產生時,訂閱者中對應的方法 onNext(), onComplete()和 onError()會被調用。Mono 表示的是包含 0 或者 1 個元素的異步序列。該序列中同樣可以包含與 Flux 相同的三種類型的消息通知。Flux 和 Mono 之間可以進行轉換。對一個 Flux 序列進行計數操作,得到的結果是一個 Mono對象。把兩個 Mono 序列合并在一起,得到的是一個 Flux 對象。
2.2?handler 和 filter
看了網上一些資料,從 ReactorHttpHandlerAdapter.apply 開始,debug 看看從哪發起的。
HttpServerHandle.onStateChange 這個是監聽連接狀態的方法,可以看到請求剛進來的時候是 request_received
HttpWebHandlerAdapter.apply ,包裝模式,request 和 response,繼續執行 handle方法,生成 exchange 對象,將 request ,response 還有其他的 attribute 封裝到一個對象
之后進去 Dispatcherhandler.handle ,這里邊會有3個操作,獲取路由(getHandler)、請求路由(invokeHandler)、解析結果(handleResult)
獲取路由:AbstractHandlerMapping.getHandler (代碼沒貼,有個判斷 是否跨域配置的判斷) 中間調用RoutePredicateHandlerMapping.getHandlerInternal,從RouteLocator 獲取 路由信息
請求路由:默認走的是 SimpleHandlerAdapter.handle
FilteringWebHandler.handle,獲取路由對象和對應的 filter,經過 過濾器鏈,默認是9個全局過濾器,主要看下 NettyRoutingFilter 和 NettyWriteResponseFilter
NettyRoutingFilter.filter 就是發送http請求,調用第三方服務,對response 請求頭過濾處理,將response 封裝到 Mono
NettyWriteResponseFilter.filter
可以看出來這時候netty 已經響應結果,并且往 exchange的reponse 寫入
會判斷響應的 content-type 是流還是其他的,如果是流的話,寫入并刷新。這個地方看一下 wrap 方法,我找了半天都沒有找到 gateway 在哪保存的第三方服務的返回值,就在這個byteBuf,封裝 DataBuffer,設置到 DataBufferFactory,和 response 綁定。
看一下 wrap 方法
之后的方法調用 ReactorServerHttpResponse.writeWithInternal ,感興趣可以看出,代碼就不貼了。
由于 SimpleHandlerAdapter 返回的是 `Mono.empty()` ,所以不會觸發 handleResult 方法。
其中還有HttpServerHandle.onStateChange 監聽到其他的狀態,也不貼了。
3.? 總結
以上就是 gateway 收到請求后,到返回一系列的流程,內容也不是特別全。
監聽到請求進入:HttpServerHandle.onStateChange(newState = request_received) ->
包裝 request和response:ReactorHttpHandlerAdapter.apply ->
生成 exchange(包含 request和 response),用于netty請求 : HttpWebHandlerAdapter.apply ->
獲取路由、請求路由、解析結果:Dispatcherhandler.handle ->
獲取路由 AbstractHandlerMapping.getHandler:-> RoutePredicateHandlerMapping.getHandlerInternal
請求路由:SimpleHandlerAdapter.handle:-> FilteringWebHandler.handle
默認9個全局過濾器:
發送http請求,調用第三方服務,對response 請求頭過濾處理,將response 封裝到 Mono:NettyRoutingFilter.filter
獲取netty 響應結果,并且往 exchange的reponse 寫入:NettyWriteResponseFilter.filter
結果解析:ResponseBodyResultHandler.handleResult (由于 SimpleHandlerAdapter 返回的是 Mono.empty(),所以不會觸發 handleResult 方法)
寫入response并返回:NettyWriteResponseFilter.wrap (byteBuf,封裝 DataBuffer,設置到 DataBufferFactory,和 response 綁定)
?
所以看到有一些想在網關層面修改 response 的需求,只需要增加一個filter 修改 response綁定的 DataBufferFactory 中的 DataBuffer 即可。
?
還有一些不錯的文章推薦:
https://developer.ibm.com/zh/articles/j-cn-with-reactor-response-encode/
https://blog.csdn.net/chengqiuming/article/details/103394337
https://www.jianshu.com/p/c40a757fad01
?
?
?
總結
以上是生活随笔為你收集整理的springcloud gateway 源码解析、请求响应流程、第三方响应结果在 gateway 的经过的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 修改mysql的用户密码
- 下一篇: java 实现 常见排序算法(三)快速排