日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Cloud Gateway一次请求调用源码解析

發布時間:2024/8/23 javascript 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Cloud Gateway一次请求调用源码解析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介:?最近通過深入學習Spring Cloud Gateway發現這個框架的架構設計非常簡單、有效,很多組件的設計都非常值得學習,本文就Spring Cloud Gateway做一個簡單的介紹,以及針對一次請求Spring Cloud Gateway的處理流程做一個較為詳細的分析。

作者 | 尋箏
來源 | 阿里技術公眾號

一 前言

最近通過深入學習Spring Cloud Gateway發現這個框架的架構設計非常簡單、有效,很多組件的設計都非常值得學習,本文就Spring Cloud Gateway做一個簡單的介紹,以及針對一次請求Spring Cloud Gateway的處理流程做一個較為詳細的分析。

二 簡介

Spring Cloud Gateway 即Spring官方推出的一款API網關,該框架包含了Spring5、SpringBoot2、Project Reactor,其中底層通信框架用的netty。Spring Cloud Gateway在推出之初的時候,Netflix公司已經推出了類似功能的API網關框架ZUUL,但ZUUL有一個缺點是通信方式是阻塞的,雖然后來升級到了非阻塞式的ZUUL2,但是由于Spring Cloud Gateway已經推出一段時間,同時自身也面臨資料少、維護性較差的因素沒有被廣泛應用。

1 關鍵術語

在使用Spring Cloud Gateway的時候需要理解三個模塊,即

Route:

即一套路由規則,是集URI、predicate、filter等屬性的一個元數據類。

Predicate:

這是Java8函數式編程的一個方法,這里可以看做是滿足什么條件的時候,route規則進行生效。

Filter:

filter可以認為是Spring Cloud Gateway最核心的模塊,熔斷、安全、邏輯執行、網絡調用都是filter來完成的,其中又細分為gateway filter和global filter,區別在于是具體一個route規則生效還是所有route規則都生效。

可以先上一段代碼來看看:

@RequestMapping("/paramTest")public Object paramTest(@RequestParam Map<String,Object> param) {return param.get("name");}@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes().route("path_route", r ->r.path("/get").filters(f -> f.addRequestParameter("name", "value")).uri("forward:///paramTest")).build();}
  • route方法代表的就是一個路由規則;
  • path方法代表的就是一個predicate,背后的現實是PathRoutePredicateFactory,在這段代碼的含義即當路徑包含/get的時候,當前規則生效。
  • filters方法的意思即給當前路由規則添加一個增加請求參數的filter,每次請求都對參數里添加 name:value 的鍵值對;
  • uri 方法的含義即最終路由到哪里去,這里的forward前綴會將請求交給spring mvc的DispatcherHandler進行路由,進行本機的邏輯調用,除了forward以外還可以使用http、https前綴進行http調用,lb前綴可以在配置注冊中心后進行rpc調用。

上圖是Spring Cloud Gateway官方文檔給出的一個工作原理圖,Spring Cloud Gateway 接收到請求后進行路由規則的匹配,然后交給web handler 進行處理,web handler 會執行一系列的filter邏輯。

三 流程分析

1 接受請求

Spring Cloud Gateway的底層框架是netty,接受請求的關鍵類是ReactorHttpHandlerAdapter,做的事情很簡單,就是將netty的請求、響應轉為http的請求、響應并交給一個http handler執行后面的邏輯,下圖為該類的源碼僅保留核心邏輯。

@Overridepublic Mono< Void> apply(HttpServerRequest request, HttpServerResponse response) {NettyDataBufferFactory bufferFactory = new NettyDataBufferFactory(response.alloc());ServerHttpRequest adaptedRequest;ServerHttpResponse adaptedResponse;//轉換請求try {adaptedRequest = new ReactorServerHttpRequest(request, bufferFactory);adaptedResponse = new ReactorServerHttpResponse(response, bufferFactory);}catch (URISyntaxException ex) {if (logger.isWarnEnabled()) {...}...return this.httpHandler.handle(adaptedRequest, adaptedResponse).doOnError(ex -> logger.warn("Handling completed with error: " + ex.getMessage())).doOnSuccess(aVoid -> logger.debug("Handling completed with success"));}

2 WEB過濾器鏈

http handler做的事情第一是將request 和 response轉為一個exchange,這個exchange非常核心,是各個filter之間參數流轉的載體,該類包含request、response、attributes(擴展字段),接著做的事情就是web filter鏈的執行,其中的邏輯主要是監控。

其中WebfilterChainParoxy 又會引出新的一條filter鏈,主要是安全、日志、認證相關的邏輯,由此可見Spring Cloud Gateway的過濾器設計是層層嵌套,擴展性很強。

3 尋找路由規則

核心類是RoutePredicateHandlerMapping,邏輯也非常簡單,就是把所有的route規則的predicate遍歷一遍看哪個predicate能夠命中,核心代碼是:

return this.routeLocator.getRoutes().filter(route -> {...return route.getPredicate().test(exchange);})

因為我這里用的是path進行過濾,所以背后的邏輯是PathRoutePredicateFactory來完成的,除了PathRoutePredicateFactory還有很多predicate規則。

這些路由規則都能從官方文檔上找到影子。

4 核心過濾器鏈執行

找到路由規則后下一步就是執行了,這里的核心類是FilteringWebHandler,其中的源碼為:

做的事情很簡單:

  • 獲取route級別的過濾器
  • 獲取全局過濾器
  • 兩種過濾器放在一起并根據order進行排序
  • 執行過濾器鏈
  • 因為我的配置里包含了一個添加請求參數的邏輯,所以紅線箭頭處就是我配置的gateway filter名為 AddRequestParameterGatewayFilterFactory,其余全是Gloabl Filter,這些過濾器的功能主要是url解析,請求轉發,響應回寫等邏輯,因為我們這里用的是forward schema,所以請求轉發會由ForwardRoutingFilter進行執行。

    5 請求轉發

    ForwardRoutingFilter做的事情也很簡單,直接復用了spring mvc的能力,將請求提交給dispatcherHandler進行處理,dispatcherHandler會根據path前綴找到需要目標處理器執行邏輯。

    @Override public Mono< Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {URI requestUrl = exchange.getRequiredAttribute(GATEWAY_REQUEST_URL_ATTR);String scheme = requestUrl.getScheme();if (isAlreadyRouted(exchange) || !"forward".equals(scheme)) {return chain.filter(exchange);}setAlreadyRouted(exchange);//TODO: translate url?if (log.isTraceEnabled()) {log.trace("Forwarding to URI: "+requestUrl);}return this.dispatcherHandler.handle(exchange); }

    6 響應回寫

    響應回寫的核心類是NettyWriteResponseFilter,但是大家可以注意到執行器鏈中NettyWriteResponseFilter的排序是在最前面的,按道理這種響應處理的類應該是在靠后才對,這里的設計比較巧妙。大家可以看到chain.filter(exchange).then(),意思就是執行到我的時候直接跳過下一個,等后面的過濾器都執行完后才執行這段邏輯,這種行為控制的方法值得學習。

    @Override public Mono< Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {// NOTICE: nothing in "pre" filter stage as CLIENT_RESPONSE_ATTR is not added// until the WebHandler is runreturn chain.filter(exchange).then(Mono.defer(() -> {HttpClientResponse clientResponse = exchange.getAttribute(CLIENT_RESPONSE_ATTR);if (clientResponse == null) {return Mono.empty();}log.trace("NettyWriteResponseFilter start");ServerHttpResponse response = exchange.getResponse();NettyDataBufferFactory factory = (NettyDataBufferFactory) response.bufferFactory();//TODO: what if it's not nettyfinal Flux< NettyDataBuffer> body = clientResponse.receive().retain() //TODO: needed?.map(factory::wrap);MediaType contentType = response.getHeaders().getContentType();return (isStreamingMediaType(contentType) ?response.writeAndFlushWith(body.map(Flux::just)) : response.writeWith(body));})); }

    四 總結

    整體讀完Spring Cloud Gateway請求流程代碼后,有幾點感受:

  • 過濾器是Spring Cloud Gateway最核心的設計,甚至于可以夸張說Spring Cloud Gateway是一個過濾器鏈執行框架而不是一個API網關,因為API網關實際的請求轉發、請求響應回寫都是在過濾器中做的,這些是Spring Cloud Gateway感知不到的邏輯。
  • Spring Cloud Gateway路由規則獲取的模塊具備優化的空間,因為是循環遍歷進行獲取的,如果每個route規則較多,predicate規則較復雜,就可以考慮用map進行優化了,當日route規則,predicate規則也不會很復雜,兼顧到代碼的可讀性,當前方式也沒有什么問題。
  • 作為API網關框架,內置了非常多的過濾器,如果有過濾器的卸載功能可能會更好,用戶可用根據實際情況卸載不必要的功能,背后減少的邏輯開銷,在調用量極大的API網關場景,收益也會很可觀。
  • 原文鏈接
    本文為阿里云原創內容,未經允許不得轉載。?

    總結

    以上是生活随笔為你收集整理的Spring Cloud Gateway一次请求调用源码解析的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。