自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

網(wǎng)絡(luò) 通信技術(shù)
本節(jié)主要了解系統(tǒng)中的謂詞與配置的路由信息是如何進(jìn)行初始化關(guān)聯(lián)生成路由對(duì)象的。每個(gè)謂詞工廠中的Config對(duì)象又是如何被解析配置的。

[[409660]]

 環(huán)境:springcloud Hoxton.SR11

本節(jié)主要了解系統(tǒng)中的謂詞與配置的路由信息是如何進(jìn)行初始化關(guān)聯(lián)生成路由對(duì)象的。每個(gè)謂詞工廠中的Config對(duì)象又是如何被解析配置的。

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

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

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

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

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

所有的謂詞工廠繼承的

AbstractRoutePredicateFactory中的泛型都是內(nèi)部類的Config。這個(gè)是如何被配置上值的呢?

6.1 gateway自動(dòng)配置

在下面這個(gè)類中配置了所有的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.   } 

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

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

注意:這里的路由信息是在容器啟動(dòng)后就會(huì)被初始化的。

  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.   } 

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

RouteDefinitionRouteLocator

RouteDefinitionRouteLocator構(gòu)造函數(shù)中的initFactories方法用來(lái)映射路由工廠的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.   }); 

方法中解析每一個(gè)謂詞工廠對(duì)應(yīng)的名稱然后緩存到predicates 集合中。

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

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

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

RouteDefinitionRouteLocator進(jìn)行了合并。

6.2 生成路由對(duì)象Route及Config配置

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

根據(jù)上面的自動(dòng)配置也知道了在服務(wù)啟動(dòng)時(shí)就進(jìn)行初始化所有路由信息了。

獲取路由信息

  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; 

進(jìn)入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進(jìn)行關(guān)聯(lián)設(shè)置值 
  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.   // 最終調(diào)用謂詞工廠(XxxRoutePredicateFactory的apply方法返回RoutePredicate該對(duì)象繼承Predicate) 
  14.   return factory.applyAsync(config); 

lookup方法中查找,也就是在這里將對(duì)應(yīng)的謂詞Config與RouteDefinition(Predicate)中定義的相對(duì)應(yīng)的屬性關(guān)聯(lián)。

進(jìn)入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圖當(dāng)前apply所有的實(shí)現(xiàn)就是系統(tǒng)內(nèi)部定義的XxxRoutePredicateFactory 
  5.   } 
  6. // apply(config),如這里配置了Path謂詞,那么就會(huì)進(jìn)入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. // 最后返回一個(gè)異步的謂詞 
  15. public static AsyncPredicate<ServerWebExchange> toAsyncPredicate(Predicate<? super ServerWebExchange> predicate) { 
  16.   Assert.notNull(predicate, "predicate must not be null"); 
  17.   // 這里from就是返回一個(gè)DefaultAsyncPredicate默認(rèn)的異步謂詞 
  18.   return AsyncPredicate.from(predicate); 
  19. static AsyncPredicate<ServerWebExchange> from( Predicate<? super ServerWebExchange> predicate) { 
  20.   return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate)); 
SpringCloud Gateway 路由配置定位原理分析

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

  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對(duì)象會(huì)被保存在上面說(shuō)的

CachingRouteLocator.routes中。

6.3 定位路由

根據(jù)上面的配置RouteLocator 該類用來(lái)定位路由(查找具體的使用哪個(gè)路由);當(dāng)一個(gè)請(qǐng)求過(guò)來(lái)會(huì)查找是哪個(gè)路由。

RouteLocator中定義了一個(gè)方法

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

查看這個(gè)getRoutes方法是誰(shuí)調(diào)用的 

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

看到這個(gè)

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

接下來(lái)回到前面說(shuō)的

RequestMappingHanlderMapping 對(duì)象,當(dāng)我們請(qǐng)求一個(gè)路由地址時(shí)會(huì)執(zhí)行該類中的lookup方法查找路由

  1. protected Mono<Route> lookupRoute(ServerWebExchange exchange) { 
  2.   // 這里的this.routeLocator就是 CachingRouteLocator對(duì)象  
  3.   return this.routeLocator.getRoutes() 
  4.       .concatMap(route -> Mono.just(route).filterWhen(r -> { 
  5.         exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId()); 
  6.         // 過(guò)濾查找符合的路由   
  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.      }); 

進(jìn)入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.  

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

調(diào)用GatewayPredicate.test返回判斷當(dāng)前請(qǐng)求的路由是否匹配。

整體的一個(gè)流程:

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

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

3、根據(jù)請(qǐng)求路由路徑查找匹配的路由

 

責(zé)任編輯:姜華 來(lái)源: 今日頭條
相關(guān)推薦

2023-07-20 10:04:37

底層路由配置

2023-08-11 08:42:49

泛型工廠繼承配置

2021-03-26 06:01:45

日志MongoDB存儲(chǔ)

2023-05-04 08:09:33

serviceId路徑謂詞中心注冊(cè)

2019-09-10 13:58:57

動(dòng)態(tài)路由路由器網(wǎng)絡(luò)

2009-12-23 17:33:02

光纖路由技術(shù)

2010-07-08 15:08:12

2022-05-12 08:21:13

項(xiàng)目網(wǎng)關(guān)模塊

2022-06-12 07:27:39

微服務(wù)GateWay

2022-05-16 08:22:11

網(wǎng)關(guān)過(guò)濾器路由

2021-08-26 11:52:32

FeignWeb服務(wù)

2020-11-18 11:26:45

SpringCloudZuulJava

2009-12-15 13:35:18

路由協(xié)議分析儀

2009-11-11 14:18:00

動(dòng)態(tài)路由協(xié)議

2010-01-22 17:56:31

千兆路由交換機(jī)

2010-10-14 14:46:23

無(wú)線路由器配置

2009-12-09 10:07:22

配置靜態(tài)路由

2023-10-16 22:07:20

Spring配置中心Bean

2025-01-15 13:30:48

FeignHTTPJava

2009-12-11 15:41:16

路由交換機(jī)配置
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)