日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Java源碼解析之Gateway請求轉發

瀏覽:27日期:2022-08-09 18:29:26
Gateway請求轉發

本期我們主要還是講解一下Gateway,上一期我們講解了一下Gateway中進行路由轉發的關鍵角色,過濾器和斷言是如何被加載的,上期鏈接://www.jb51.net/article/211824.htm

好了我們廢話不多說,開始今天的Gateway請求轉發流程講解,為了在講解源碼的時候,以防止大家可能會迷糊,博主專門畫了一下源碼流程圖,鏈接地址://www.jb51.net/article/211824.htm

上一期我們已經知道了相關類的加載,今天直接從源碼開始,大家可能不太了解webflux和reactor這種響應式編程,畢竟不是主流,我們一直用的都是spring MVC,沒事,我們主要講解流程,不做過多的講解。

大家先看下面的代碼,我們今天主要的代碼入口就是這里:

public Mono<Void> handle(ServerWebExchange exchange) {if (logger.isDebugEnabled()) { ServerHttpRequest request = exchange.getRequest(); logger.debug('Processing ' + request.getMethodValue() + ' request for [' + request.getURI() + ']');}if (this.handlerMappings == null) { return Mono.error(HANDLER_NOT_FOUND_EXCEPTION);}return Flux.fromIterable(this.handlerMappings).concatMap(mapping -> mapping.getHandler(exchange)).next().switchIfEmpty(Mono.error(HANDLER_NOT_FOUND_EXCEPTION)).flatMap(handler -> invokeHandler(exchange, handler)).flatMap(result -> handleResult(exchange, result)); }

第一步,我們先來看一看幾個主要的類及其方法,Flux 表示的是包含 0 到 N 個元素的異步序列,Mono 表示的是包含 0 或者 1 個元素的異步序列,記住Flux是多個元素集合,Mono 是單個元素集合就很好理解以后的源碼了,以下方法注釋是博主為了大家好理解而寫的,具體實際的意義還是需要大家自行Google學習了。

Mono.empty();創建一個空Mono對象;

Mono.just(**);創建一個**元素的對象;

Mono.then(**);在最后執行,相當于spring的aop后置通知一樣

開始我們的第一步解析:mapping.getHandler(exchange);本方法主要做的是獲取路由,我們繼續看一看底層源碼:

Java源碼解析之Gateway請求轉發getHandler

Java源碼解析之Gateway請求轉發getHandlerInternal

//這里返回的是單個對象 protected Mono<Route> lookupRoute(ServerWebExchange exchange) {return this.routeLocator//我們一會主要看一下這個方法.getRoutes()//individually filter routes so that filterWhen error delaying is not a problem.concatMap(route -> Mono.just(route).filterWhen(r -> { // add the current route we are testing exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId()); //只返回一個符合斷言的路由配置,所以整個流程先匹配斷言 return r.getPredicate().apply(exchange);})//instead of immediately stopping main flux due to error, log and swallow it.doOnError(e -> logger.error('Error applying predicate for route: '+route.getId(), e)).onErrorResume(e -> Mono.empty()))// .defaultIfEmpty() put a static Route not found// or .switchIfEmpty()// .switchIfEmpty(Mono.<Route>empty().log('noroute')).next()//TODO: error handling.map(route -> { if (logger.isDebugEnabled()) {logger.debug('Route matched: ' + route.getId()); } validateRoute(route, exchange); return route;}); }

我們現在看看Route對象是怎么在getRoutes()創建的。

public Flux<Route> getRoutes() {return this.routeDefinitionLocator.getRouteDefinitions() //這一步是從配置文件中讀取我們配置的路由定義.map(this::convertToRoute)//這一步會加載我們配置給路由的斷言與過濾器形成路由對象//TODO: error handling.map(route -> { if (logger.isDebugEnabled()) {logger.debug('RouteDefinition matched: ' + route.getId()); } return route;}); }

//關鍵的代碼在這里 private Route convertToRoute(RouteDefinition routeDefinition) { //這兩步才會跟上一章節講解的如何加載斷言與過濾器有關聯,大家可以自行查看底層源碼是如何查出來的對象的AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);List<GatewayFilter> gatewayFilters = getFilters(routeDefinition); //終于生成了路由對象return Route.async(routeDefinition).asyncPredicate(predicate).replaceFilters(gatewayFilters).build(); }

這里大家要記住getHandlerInternal方法,生成了Mono.just(webHandler),仔細看webHandler是FilteringWebHandler對象,以后用到這個WebHandler,好了路由生成也選擇完畢了,我們應該知道改請求是否符合我們配置的過濾器了,因為過濾器還沒用上,斷言只負責了選擇哪一個路由生效。

//我們看下一個主流程的方法 private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {if (this.handlerAdapters != null) { for (HandlerAdapter handlerAdapter : this.handlerAdapters) {if (handlerAdapter.supports(handler)) {//這里走的是SimpleHandlerAdapter,可以自己debug發現,也可以去找自動配置類找,這里就不講解了 return handlerAdapter.handle(exchange, handler);} }}return Mono.error(new IllegalStateException('No HandlerAdapter: ' + handler)); }

public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {WebHandler webHandler = (WebHandler) handler;//讓大家記住的那個FilteringWebHandler類,終于在這里起作用了。我們這回可以看看過濾器是如何起作用的Mono<Void> mono = webHandler.handle(exchange); return mono.then(Mono.empty());//過濾器處理完后,開始處理mono.then方法 }

public Mono<Void> handle(ServerWebExchange exchange) {Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);List<GatewayFilter> gatewayFilters = route.getFilters();//我們路由自己配置的過濾器//加載全局過濾器List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);combined.addAll(gatewayFilters);//TODO: needed or cached?AnnotationAwareOrderComparator.sort(combined);//排序if (logger.isDebugEnabled()) { logger.debug('Sorted gatewayFilterFactories: '+ combined);}//形成過濾器鏈,開始調用filter進行過濾。這里剩下的我們就不講解,跟spring配置的過濾器鏈調用流程是一樣的return new DefaultGatewayFilterChain(combined).filter(exchange); }

至此,我們的請求流程基本完事了,我們再來看看幾個主要的全局過濾器配置。LoadBalancerClientFilter:負責獲取服務器ip的過濾器,NettyRoutingFilter:負責轉發我們請求的過濾器。

這里主要講解Gateway流程,關于Ribbon的代碼我們就不做主要講解了

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);//所以要加上lb前綴,才會走該過濾器if (url == null || (!'lb'.equals(url.getScheme()) && !'lb'.equals(schemePrefix))) { return chain.filter(exchange);}//preserve the original urladdOriginalRequestUrl(exchange, url);log.trace('LoadBalancerClientFilter url before: ' + url);//選擇實例final ServiceInstance instance = choose(exchange);......return chain.filter(exchange); }

看主要代碼即可,非必要的看了也暈。

public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {.......//通過httpClient發送請求獲取響應Mono<HttpClientResponse> responseMono = this.httpClient.request(method, url, req -> { final HttpClientRequest proxyRequest = req.options(NettyPipeline.SendOptions::flushOnEach) .headers(httpHeaders) .chunkedTransfer(chunkedTransfer) .failOnServerError(false) .failOnClientError(false); if (preserveHost) {String host = request.getHeaders().getFirst(HttpHeaders.HOST);proxyRequest.header(HttpHeaders.HOST, host); } if (properties.getResponseTimeout() != null) {proxyRequest.context(ctx -> ctx.addHandlerFirst(new ReadTimeoutHandler(properties.getResponseTimeout().toMillis(), TimeUnit.MILLISECONDS))); } return proxyRequest.sendHeaders() //I shouldn’t need this .send(request.getBody().map(dataBuffer -> ((NettyDataBuffer) dataBuffer).getNativeBuffer()));});return responseMono.doOnNext(res -> {...} }

我們今天主要看的是Gateway的主要請求轉發的流程,像webflux這種我們沒有精力學習的,可以暫時略過,畢竟也不是主流。我們今天最后總結一下。首先在Gateway這兩章的點,項目啟動時加載斷言與過濾器->接收請求時添加配置文件中的路由配置并生成路由對象->找到符合斷言的路由->除了個人配置的過濾器聯合全局過濾器生成過濾器鏈,并逐步過濾知道所有調用完成。

其中我們主要分析了兩個主要的全局過濾器:LoadBalancerClientFilter:負責獲取服務器ip的過濾器,NettyRoutingFilter:負責轉發我們請求的過濾器。

到此這篇關于Java源碼解析之Gateway請求轉發的文章就介紹到這了,更多相關Gateway請求轉發內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Java
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
精品丝袜久久| 国产乱码精品一区二区亚洲| 免费不卡中文字幕在线| 日韩二区三区四区| а√天堂8资源在线| 蜜臀久久久99精品久久久久久| 国产欧美一区二区色老头| 激情欧美一区二区三区| 国产精品极品| 日韩在线卡一卡二| caoporn视频在线| 日韩黄色免费网站| 日韩精品1区| 麻豆久久一区二区| 亚洲天堂av资源在线观看| 国产va在线视频| 国产精品成人国产| 视频在线观看一区| 亚洲二区三区不卡| 香蕉视频亚洲一级| 欧美激情五月| 欧美日韩va| 亚洲一区二区三区在线免费| 中文在线а√天堂| 国产精品久久久久久久久久久久久久久 | 亚洲天堂成人| 欧美在线综合| 91九色精品国产一区二区| 涩涩av在线| 成人三级高清视频在线看| 欧美日韩调教| 欧美日本二区| 日本va欧美va瓶| 综合色就爱涩涩涩综合婷婷| 水蜜桃久久夜色精品一区的特点 | 国产精品一区二区中文字幕| 日本在线视频一区二区| 日韩精品视频一区二区三区| 亚洲综合色婷婷在线观看| 亚洲一区有码| 国产人成精品一区二区三| 国产精品一线天粉嫩av| 麻豆精品在线视频| 高清av不卡| 999精品在线| 99久久久国产精品美女| 欧美中文字幕一区二区| 日韩一级精品| 日韩欧美在线精品| 国产精品网在线观看| 久久99影视| 亚洲国产专区校园欧美| 综合一区av| 里番精品3d一二三区| 精品久久在线| 日韩一级精品| 国产日韩一区| 日韩精品欧美| 亚洲一区二区三区高清不卡| 日韩高清电影免费| 国产精品久久久久久妇女| 久久久久久夜| 午夜a一级毛片亚洲欧洲| 精品72久久久久中文字幕| 尤物在线精品| 国产精品久久久久久妇女| 久久久亚洲一区| 欧美精品国产白浆久久久久| 欧美sss在线视频| 日韩黄色av| 红桃视频欧美| 精品久久久久久久| 亚洲日韩视频| 久久久水蜜桃av免费网站| 日本亚洲视频| 日韩不卡免费高清视频| 丝袜诱惑制服诱惑色一区在线观看| 久久精品国产网站| 亚洲欧美视频一区二区三区| 国产一区一一区高清不卡| 一区二区三区四区在线观看国产日韩| 成人综合一区| 欧美国产另类| 欧美片第1页综合| 中文字幕一区二区av| 蜜臀91精品国产高清在线观看 | 国产色99精品9i| 亚洲婷婷丁香| 久久要要av| 国产免费播放一区二区| 国产精品美女久久久| 99热国内精品| sm久久捆绑调教精品一区| 美女国产一区二区三区| 青青青国产精品| 日韩欧美中文在线观看| 亚洲免费观看高清完整版在线观| 99亚洲视频| 夜夜嗨一区二区三区| 不卡av一区二区| 激情综合亚洲| 黄色日韩精品| 免费欧美在线视频| 蜜桃一区二区三区在线| 一区在线免费| 国产免费成人| 视频一区日韩| 国产日韩欧美三区| 国产精品流白浆在线观看| 精品伊人久久久| 福利一区和二区| 在线观看精品| 国产亚洲精品久久久久婷婷瑜伽| 99国产精品久久久久久久| 最近国产精品视频| 欧美综合精品| 精品国产亚洲一区二区三区| 国产在线日韩精品| 视频福利一区| 美女久久一区| 日韩欧美中文字幕电影| 国产精品密蕾丝视频下载| 四虎8848精品成人免费网站| 久久精品123| 亚洲午夜久久| 久久天堂影院| 欧美另类综合| 国产免费久久| 免费黄色成人| 91欧美极品| 久久久成人网| 日韩av电影一区| 日韩免费福利视频| 午夜天堂精品久久久久| 精品国产一区二区三区av片| 电影亚洲精品噜噜在线观看| 日韩在线一区二区| 精品国产美女a久久9999| 亚洲激情不卡| 久久久男人天堂| 亚洲理论在线| 国产福利片在线观看| 亚洲精品日韩久久| 99久久久久久中文字幕一区| 国产色噜噜噜91在线精品| 亚州av乱码久久精品蜜桃| 欧美国产日本| 在线精品一区二区| 国产精品99免费看| 久久av网址| 亚洲影院天堂中文av色| 99视频精品视频高清免费| 福利欧美精品在线| 国产欧美一区二区三区国产幕精品| 亚洲二区在线| 国产精选在线| 卡一精品卡二卡三网站乱码| 蜜臀a∨国产成人精品| 免费av一区| 久久精品亚洲人成影院| 日产精品一区二区| 久久爱www.| 国产精品久久久久毛片大屁完整版| 亚洲精品看片| 午夜一区在线| 亚洲午夜在线| 欧美日韩色图| 亚洲一级少妇| 色婷婷色综合| 视频二区不卡| 日韩高清欧美| 欧美色图一区| 亚洲一区欧美二区| 亚洲一区欧美激情| 亚洲影视一区二区三区| 亚洲啊v在线免费视频| 日韩一区精品| 欧美视频二区| 国产高清日韩| 精品国产不卡| 国产成人精品一区二区免费看京| 麻豆精品视频在线| 日韩电影免费网站| 91久久视频| 亚洲精品精选| 久久福利在线| 中国字幕a在线看韩国电影| 成人片免费看| 999在线观看精品免费不卡网站| 国产亚洲在线观看| 欧美亚洲二区| а√在线中文在线新版| 午夜精品免费| 国产另类在线| 国产日韩电影| 欧美日韩一二三四| 91成人小视频| 日韩免费一区| 天堂va欧美ⅴa亚洲va一国产| 国产精品啊v在线|