成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

SpringCloud Gateway 路由配置定位原理分析

網絡 通信技術
本節主要了解系統中的謂詞與配置的路由信息是如何進行初始化關聯生成路由對象的。每個謂詞工廠中的Config對象又是如何被解析配置的。

[[409660]]

 環境:springcloud Hoxton.SR11

本節主要了解系統中的謂詞與配置的路由信息是如何進行初始化關聯生成路由對象的。每個謂詞工廠中的Config對象又是如何被解析配置的。

所有的謂詞工廠中的Config中屬性值是如何被配置的。

在SpringCloud Gateway中的所有謂詞工廠如下:

SpringCloud Gateway 路由配置定位原理分析

命名規則:XxxRoutePredicateFactory。所有的這些謂詞工廠都是如下的繼承關系

  1. public class MethodRoutePredicateFactory extends   AbstractRoutePredicateFactory<MethodRoutePredicateFactory.Config> 
  2. //  
  3. public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<PathRoutePredicateFactory.Config> 
  4. // ... 

所有的謂詞工廠繼承的

AbstractRoutePredicateFactory中的泛型都是內部類的Config。這個是如何被配置上值的呢?

6.1 gateway自動配置

在下面這個類中配置了所有的Predicate和Filter。

  1. public class GatewayAutoConfiguration { 
  2.   @Bean 
  3.   @ConditionalOnEnabledPredicate 
  4.   public PathRoutePredicateFactory pathRoutePredicateFactory() { 
  5.     return new PathRoutePredicateFactory(); 
  6.   } 
  7.   @Bean 
  8.   @ConditionalOnEnabledPredicate 
  9.   public QueryRoutePredicateFactory queryRoutePredicateFactory() { 
  10.     return new QueryRoutePredicateFactory(); 
  11.   } 
  12.   @Bean 
  13.   public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GatewayFilterFactory> gatewayFilters, List<RoutePredicateFactory> predicates, RouteDefinitionLocator routeDefinitionLocator, ConfigurationService configurationService) { 
  14.     return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, 
  15.             gatewayFilters, properties, configurationService); 
  16.   } 
  17.   @Bean 
  18.   @Primary 
  19.   @ConditionalOnMissingBean(name = "cachedCompositeRouteLocator"
  20.   public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) { 
  21.     return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators))); 
  22.   } 

這里會層層委托最終查找查找路由定位會交給

RouteDefinitionRouteLocator。CachingRouteLocator起到緩存的作用,將配置的所有路由信息保存。

注意:這里的路由信息是在容器啟動后就會被初始化的。

  1. public class CachingRouteLocator { 
  2.   private final RouteLocator delegate; 
  3.  
  4.   private final Flux<Route> routes; 
  5.  
  6.   private final Map<String, List> cache = new ConcurrentHashMap<>(); 
  7.  
  8.   private ApplicationEventPublisher applicationEventPublisher; 
  9.  
  10.   public CachingRouteLocator(RouteLocator delegate) { 
  11.     this.delegate = delegate; 
  12.     routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class) .onCacheMissResume(this::fetch); 
  13.   } 
  14.  
  15.   private Flux<Route> fetch() { 
  16.     return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE); 
  17.   } 

實例化CachingRouteLocator就開始查找所有配置的Route信息。最終的會委托給

RouteDefinitionRouteLocator

RouteDefinitionRouteLocator構造函數中的initFactories方法用來映射路由工廠的XxxRoutePredicateFactory。

  1. private void initFactories(List<RoutePredicateFactory> predicates) { 
  2.   predicates.forEach(factory -> { 
  3.     String key = factory.name(); 
  4.     if (this.predicates.containsKey(key)) { 
  5.       this.logger.warn("A RoutePredicateFactory named " + key + " already exists, class: " + this.predicates.get(key) + ". It will be overwritten."); 
  6.     } 
  7.     this.predicates.put(key, factory); 
  8.   }); 

方法中解析每一個謂詞工廠對應的名稱然后緩存到predicates 集合中。

factory.name()方法解析謂詞名稱。

  1. default String name() { 
  2.   return NameUtils.normalizeRoutePredicateName(getClass()); 

CachingRouteLocator是個緩存路由定位器,是個首選的RouteLocator(@Primary),這里將

RouteDefinitionRouteLocator進行了合并。

6.2 生成路由對象Route及Config配置

getRoutes---》convertToRoute---》combinePredicates---》lookup。

根據上面的自動配置也知道了在服務啟動時就進行初始化所有路由信息了。

獲取路由信息

  1. public Flux<Route> getRoutes() { 
  2.   Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions() .map(this::convertToRoute); 
  3.   routes = routes.onErrorContinue((error, obj) -> { 
  4.     return routes.map(route -> { 
  5.             return route; 
  6.   }); 

合并謂詞

  1. private AsyncPredicate<ServerWebExchange> combinePredicates( 
  2.             RouteDefinition routeDefinition) { 
  3.   // other code 
  4.   for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) { 
  5.     AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate); 
  6.     predicate = predicate.and(found); 
  7.   } 
  8.   return predicate; 

進入lookup中

  1. private AsyncPredicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) { 
  2.   RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName()); 
  3.   if (factory == null) { 
  4.     throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name " + predicate.getName()); 
  5.   } 
  6.   // 這里將配置中(yml文件)配置的name,args和謂詞工廠中的Config進行關聯設置值 
  7.   Object config = this.configurationService.with(factory) 
  8.     .name(predicate.getName()) 
  9.     .properties(predicate.getArgs()) 
  10.     .eventFunction((bound, properties) -> new PredicateArgsEvent( 
  11.         RouteDefinitionRouteLocator.this, route.getId(), properties)) 
  12.     .bind(); 
  13.   // 最終調用謂詞工廠(XxxRoutePredicateFactory的apply方法返回RoutePredicate該對象繼承Predicate) 
  14.   return factory.applyAsync(config); 

lookup方法中查找,也就是在這里將對應的謂詞Config與RouteDefinition(Predicate)中定義的相對應的屬性關聯。

進入factory.applyAsync方法

  1. @FunctionalInterface 
  2. public interface RoutePredicateFactory<C> extends ShortcutConfigurable, Configurable<C> { 
  3.   default AsyncPredicate<ServerWebExchange> applyAsync(C config) { 
  4.     return toAsyncPredicate(apply(config)); // 查看下面的6.2-1圖當前apply所有的實現就是系統內部定義的XxxRoutePredicateFactory 
  5.   } 
  6. // apply(config),如這里配置了Path謂詞,那么就會進入PathRoutePredicateFactory中的apply方法 
  7. public Predicate<ServerWebExchange> apply(Config config) { 
  8.   // other code     
  9.   return new GatewayPredicate() { 
  10.     public boolean test() { 
  11.       // todo     
  12.     } 
  13.   } 
  14. // 最后返回一個異步的謂詞 
  15. public static AsyncPredicate<ServerWebExchange> toAsyncPredicate(Predicate<? super ServerWebExchange> predicate) { 
  16.   Assert.notNull(predicate, "predicate must not be null"); 
  17.   // 這里from就是返回一個DefaultAsyncPredicate默認的異步謂詞 
  18.   return AsyncPredicate.from(predicate); 
  19. static AsyncPredicate<ServerWebExchange> from( Predicate<? super ServerWebExchange> predicate) { 
  20.   return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate)); 
SpringCloud Gateway 路由配置定位原理分析

最后在combinePredicates方法中將當前路由中配置的所有謂詞進行了and操作返回。最終回到convertToRoute方法中將當前路由中配置的謂詞,過濾器進行了整合包裝返回Route(一個路由對象)

  1. public class Route implements Ordered { 
  2.   private final String id; 
  3.     
  4.   private final URI uri; 
  5.     
  6.   private final int order
  7.     
  8.   private final AsyncPredicate<ServerWebExchange> predicate; 
  9.     
  10.   private final List<GatewayFilter> gatewayFilters; 
  11.     
  12.   private final Map<String, Object> metadata; 
  13. }     

這些Route對象會被保存在上面說的

CachingRouteLocator.routes中。

6.3 定位路由

根據上面的配置RouteLocator 該類用來定位路由(查找具體的使用哪個路由);當一個請求過來會查找是哪個路由。

RouteLocator中定義了一個方法

  1. public interface RouteLocator { 
  2.  
  3.   Flux<Route> getRoutes(); 
  4.  

查看這個getRoutes方法是誰調用的 

SpringCloud Gateway 路由配置定位原理分析

看到這個

RoutePredicateHandlerMapping是不是想起了Spring MVC中的HandlerMapping(我們所有的Controller都會被 RequestMappingHanlderMapping 匹配)。通過名稱也就知道了該HandlerMapping用來匹配我們的路由謂詞的誰來處理路由。

接下來回到前面說的

RequestMappingHanlderMapping 對象,當我們請求一個路由地址時會執行該類中的lookup方法查找路由

  1. protected Mono<Route> lookupRoute(ServerWebExchange exchange) { 
  2.   // 這里的this.routeLocator就是 CachingRouteLocator對象  
  3.   return this.routeLocator.getRoutes() 
  4.       .concatMap(route -> Mono.just(route).filterWhen(r -> { 
  5.         exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId()); 
  6.         // 過濾查找符合的路由   
  7.         return r.getPredicate().apply(exchange); 
  8.      }).doOnError(e -> logger.error( 
  9.           "Error applying predicate for route: " + route.getId(), 
  10.      e)).onErrorResume(e -> Mono.empty())) 
  11.         .next() 
  12.         .map(route -> { 
  13.           if (logger.isDebugEnabled()) { 
  14.             logger.debug("Route matched: " + route.getId()); 
  15.           } 
  16.           validateRoute(route, exchange); 
  17.           return route; 
  18.      }); 

進入r.getPredicate().apply(exchange)

  1. public interface AsyncPredicate<T> extends Function<T, Publisher<Boolean>> { 
  2.   static AsyncPredicate<ServerWebExchange> from(Predicate<? super ServerWebExchange> predicate) { 
  3.   return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate)); 
  4.   } 
  5.  
  6.   class DefaultAsyncPredicate<T> implements AsyncPredicate<T> { 
  7.  
  8.     private final Predicate<T> delegate; 
  9.  
  10.     public DefaultAsyncPredicate(Predicate<T> delegate) { 
  11.       this.delegate = delegate; 
  12.     } 
  13.  
  14.     @Override 
  15.     public Publisher<Boolean> apply(T t) { 
  16.       return Mono.just(delegate.test(t)); 
  17.     } 
  18.  
  19.     @Override 
  20.     public String toString() { 
  21.       return this.delegate.toString(); 
  22.     } 
  23.  
  24.   } 
  25.  

這里會調用Predicate.test方法(XxxRoutePredicateFactory中的apply方法返回的GatewayPredicate)。

調用GatewayPredicate.test返回判斷當前請求的路由是否匹配。

整體的一個流程:

1、系統先初始化所有的Predicate(謂詞)和Filter(過濾器)

2、根據配置的路由信息(過濾器,謂詞)包裝返回Route對象

3、根據請求路由路徑查找匹配的路由

 

責任編輯:姜華 來源: 今日頭條
相關推薦

2023-07-20 10:04:37

底層路由配置

2023-08-11 08:42:49

泛型工廠繼承配置

2021-03-26 06:01:45

日志MongoDB存儲

2023-05-04 08:09:33

serviceId路徑謂詞中心注冊

2019-09-10 13:58:57

動態路由路由器網絡

2009-12-23 17:33:02

光纖路由技術

2010-07-08 15:08:12

2022-06-12 07:27:39

微服務GateWay

2022-05-12 08:21:13

項目網關模塊

2022-05-16 08:22:11

網關過濾器路由

2021-08-26 11:52:32

FeignWeb服務

2020-11-18 11:26:45

SpringCloudZuulJava

2009-12-15 13:35:18

路由協議分析儀

2010-10-14 14:46:23

無線路由器配置

2009-12-09 10:07:22

配置靜態路由

2010-01-22 17:56:31

千兆路由交換機

2009-11-11 14:18:00

動態路由協議

2009-12-17 14:07:58

配置靜態路由

2009-12-11 15:41:16

路由交換機配置

2010-06-30 17:02:07

靜態路由
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 毛片毛片毛片毛片 | 久久久久久久久久久爱 | 一区二区三区欧美大片 | www.久久| 日韩精品一区在线 | 精品二| 亚洲精品免费在线 | 国产精品影视 | 真人毛片 | 精品无码三级在线观看视频 | 亚洲一级在线 | 日韩黄色小视频 | 福利影院在线看 | 成人福利在线观看 | 看片天堂| 一级做a爰片久久毛片 | 成人综合视频在线观看 | 欧美日韩视频在线 | 91午夜在线 | 欧美久| 亚洲一区 中文字幕 | 欧美一区二区三区大片 | 亚洲国产成人精品女人久久久 | 免费视频一区 | 国产一级免费视频 | 国产精品夜间视频香蕉 | 国产精品1区2区3区 一区中文字幕 | 一级黄色录像毛片 | 综合久久综合久久 | 伊人爽| 天天碰日日操 | 久久高清 | 国产精品夜间视频香蕉 | 欧美日韩一区二区电影 | 欧美 日韩 在线播放 | 激情欧美日韩一区二区 | 国产日韩一区二区三免费高清 | 欧美在线观看网站 | 亚洲精品久久久久久久久久久 | 神马影院一区二区三区 | 99久久精品免费看国产免费软件 |