SpringCloud Gateway 경로 설정 포 지 셔 닝 원리 분석

환경:springcloud Hoxton.SR 11
이 절 은 시스템 의 서술 어 와 설정 의 경로 정보 가 어떻게 초기 화 되 는 지 알 고 있 습 니 다.모든 술어 공장 의 Config 대상 은 어떻게 설정 되 어 있 습 니까?
모든 술어 공장 의 Config 속성 값 이 어떻게 설정 되 어 있 습 니까?
SpringCloud Gateway 의 모든 서술 어 공장 은 다음 과 같다.

명명 규칙:XxRoute PredicateFactory.모든 서술 어 공장 은 다음 과 같은 상속 관계 이다.

public class MethodRoutePredicateFactory extends   AbstractRoutePredicateFactory<MethodRoutePredicateFactory.Config>
// 
public class PathRoutePredicateFactory extends AbstractRoutePredicateFactory<PathRoutePredicateFactory.Config>
// ...
공장 상속
AbstractRoute Predicate Factory 의 범 형 은 모두 내부 클래스 의 Config 입 니 다.이것 은 어떻게 값 이 설정 되 어 있 습 니까?
6.1 게 이 트 웨 이 자동 설정
다음 클래스 에 모든 Predicate 와 Filter 를 설정 합 니 다.

public class GatewayAutoConfiguration {
  @Bean
  @ConditionalOnEnabledPredicate
  public PathRoutePredicateFactory pathRoutePredicateFactory() {
    return new PathRoutePredicateFactory();
  }
  @Bean
  @ConditionalOnEnabledPredicate
  public QueryRoutePredicateFactory queryRoutePredicateFactory() {
    return new QueryRoutePredicateFactory();
  }
  @Bean
  public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GatewayFilterFactory> gatewayFilters, List<RoutePredicateFactory> predicates, RouteDefinitionLocator routeDefinitionLocator, ConfigurationService configurationService) {
    return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates,
            gatewayFilters, properties, configurationService);
  }
  @Bean
  @Primary
  @ConditionalOnMissingBean(name = "cachedCompositeRouteLocator")
  public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) {
    return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators)));
  }
}
여 기 는 층 층 이 의뢰 를 해서 최종 검색 루트 를 찾 아서 위치 추적 을 맡 기 겠 습 니 다.
RouteDefinitionRouteLocator。CachingRouteLocator 는 캐 시 역할 을 하 며 설정 한 모든 경로 정 보 를 저장 합 니 다.
메모:이 경로 정 보 는 용기 가 시 작 된 후에 초기 화 됩 니 다.

public class CachingRouteLocator {
  private final RouteLocator delegate;

  private final Flux<Route> routes;

  private final Map<String, List> cache = new ConcurrentHashMap<>();

  private ApplicationEventPublisher applicationEventPublisher;

  public CachingRouteLocator(RouteLocator delegate) {
    this.delegate = delegate;
    routes = CacheFlux.lookup(cache, CACHE_KEY, Route.class) .onCacheMissResume(this::fetch);
  }

  private Flux<Route> fetch() {
    return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE);
  }
}
CachingRouteLocator 를 예화 하면 모든 설정 의 Route 정 보 를 찾기 시작 합 니 다.최종 의뢰 는
RouteDefinitionRouteLocator
RouteDefinitionRouteLocator 구조 함수 의 initFactory 방법 은 공장 의 Xxx Route PredicateFactory 를 비 추 는 데 사 용 됩 니 다.

private void initFactories(List<RoutePredicateFactory> predicates) {
  predicates.forEach(factory -> {
    String key = factory.name();
    if (this.predicates.containsKey(key)) {
      this.logger.warn("A RoutePredicateFactory named " + key + " already exists, class: " + this.predicates.get(key) + ". It will be overwritten.");
    }
    this.predicates.put(key, factory);
  });
}
방법 에서 모든 술어 공장 에 대응 하 는 이름 을 분석 하고 predicates 집합 에 캐 시 합 니 다.
factory.name()방법 은 술어 이름 을 해석 합 니 다.

default String name() {
  return NameUtils.normalizeRoutePredicateName(getClass());
}
CachingRouteLocator 는 캐 시 경로 지정 기 입 니 다.우선 선택 한 RouteLocator(@Primary)입 니 다.
Route Definition Route Locator 가 합병 되 었 습 니 다.
6.2 경로 생 성 대상 Route 및 Config 설정
getRoutes---》convertToRoute---》combinePredicates---》lookup。
위의 자동 설정 에 따 르 면 서비스 가 시 작 될 때 모든 경로 정 보 를 초기 화 하 는 것 을 알 수 있 습 니 다.
경로 정보 가 져 오기

public Flux<Route> getRoutes() {
  Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions() .map(this::convertToRoute);
  routes = routes.onErrorContinue((error, obj) -> {
    return routes.map(route -> {
            return route;
  });
}
병합 술어

private AsyncPredicate<ServerWebExchange> combinePredicates(
            RouteDefinition routeDefinition) {
  // other code
  for (PredicateDefinition andPredicate : predicates.subList(1, predicates.size())) {
    AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition, andPredicate);
    predicate = predicate.and(found);
  }
  return predicate;
}
lookup 에 들 어가 기

private AsyncPredicate<ServerWebExchange> lookup(RouteDefinition route, PredicateDefinition predicate) {
  RoutePredicateFactory<Object> factory = this.predicates.get(predicate.getName());
  if (factory == null) {
    throw new IllegalArgumentException("Unable to find RoutePredicateFactory with name " + predicate.getName());
  }
  //       (yml  )   name,args       Config       
  Object config = this.configurationService.with(factory)
    .name(predicate.getName())
    .properties(predicate.getArgs())
    .eventFunction((bound, properties) -> new PredicateArgsEvent(
        RouteDefinitionRouteLocator.this, route.getId(), properties))
    .bind();
  //         (XxxRoutePredicateFactory apply    RoutePredicate     Predicate)
  return factory.applyAsync(config);
}
lookup 방법 에서 찾 습 니 다.즉,여기 서 대응 하 는 서술 어 Config 와 Route Definition(Predicate)에서 정의 하 는 대응 하 는 속성 과 연 결 됩 니 다.
factory.apply Async 에 들 어 가 는 방법

@FunctionalInterface
public interface RoutePredicateFactory<C> extends ShortcutConfigurable, Configurable<C> {
  default AsyncPredicate<ServerWebExchange> applyAsync(C config) {
    return toAsyncPredicate(apply(config)); //      6.2-1   apply              XxxRoutePredicateFactory
  }
}
// apply(config),      Path  ,      PathRoutePredicateFactory  apply  
public Predicate<ServerWebExchange> apply(Config config) {
  // other code    
  return new GatewayPredicate() {
    public boolean test() {
      // todo    
    }
  }
}
//            
public static AsyncPredicate<ServerWebExchange> toAsyncPredicate(Predicate<? super ServerWebExchange> predicate) {
  Assert.notNull(predicate, "predicate must not be null");
  //   from      DefaultAsyncPredicate       
  return AsyncPredicate.from(predicate);
}
static AsyncPredicate<ServerWebExchange> from( Predicate<? super ServerWebExchange> predicate) {
  return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate));
}
그림 6.2-1

마지막 으로 combinePredicates 방법 에서 현재 경로 에 설 정 된 모든 서술 어 를 and 작업 으로 되 돌려 줍 니 다.최종 적 으로 convertToRoute 방법 으로 돌아 가 현재 경로 에 설 치 된 서술 어,필 터 를 통합 포장 하여 Route(경로 대상)로 되 돌려 줍 니 다.

public class Route implements Ordered {
  private final String id;
   
  private final URI uri;
   
  private final int order;
   
  private final AsyncPredicate<ServerWebExchange> predicate;
   
  private final List<GatewayFilter> gatewayFilters;
   
  private final Map<String, Object> metadata;
}
이 Route 대상 들 은 위 에 저장 되 어 있 습 니 다.
CachingRoute Locator.routes 중 입 니 다.
6.3 포 지 셔 닝 경로
위의 설정 에 따라 RouteLocator 와 같은 종 류 는 경 로 를 찾 습 니 다(구체 적 으로 어떤 경 로 를 사용 하 는 지 찾 습 니 다).요청 이 오 면 어떤 경로 인지 찾 을 수 있 습 니 다.
RouteLocator 에서 방법 을 정 의 했 습 니 다.

public interface RouteLocator {

  Flux<Route> getRoutes();

}
이 getRoutes 방법 을 누가 호출 했 는 지 확인 합 니 다.

이거 보니까.
Route Predicate Handler Mapping 은 Spring MVC 의 Handler Mapping 을 떠 올 렸 습 니까?이름 을 통 해 알 수 있 듯 이 이 Handler Mapping 은 우리 의 경로 서술 어 에 맞 는 누가 경 로 를 처리 하 는 지 알 수 있 습 니 다.
이제 앞으로 돌아 가서 말씀 드 리 겠 습 니 다.
Request MappingHanlder Mapping 대상 은 루트 주 소 를 요청 할 때 이 클래스 의 lookup 방법 을 실행 하여 루트 를 찾 습 니 다

protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
  //    this.routeLocator   CachingRouteLocator   
  return this.routeLocator.getRoutes()
      .concatMap(route -> Mono.just(route).filterWhen(r -> {
        exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
        //            
        return r.getPredicate().apply(exchange);
     }).doOnError(e -> logger.error(
          "Error applying predicate for route: " + route.getId(),
     e)).onErrorResume(e -> Mono.empty()))
        .next()
        .map(route -> {
          if (logger.isDebugEnabled()) {
            logger.debug("Route matched: " + route.getId());
          }
          validateRoute(route, exchange);
          return route;
     });
}
r.getPredicate().apply(exchange)에 들 어가 기

public interface AsyncPredicate<T> extends Function<T, Publisher<Boolean>> {
  static AsyncPredicate<ServerWebExchange> from(Predicate<? super ServerWebExchange> predicate) {
  return new DefaultAsyncPredicate<>(GatewayPredicate.wrapIfNeeded(predicate));
  }

  class DefaultAsyncPredicate<T> implements AsyncPredicate<T> {

    private final Predicate<T> delegate;

    public DefaultAsyncPredicate(Predicate<T> delegate) {
      this.delegate = delegate;
    }

    @Override
    public Publisher<Boolean> apply(T t) {
      return Mono.just(delegate.test(t));
    }

    @Override
    public String toString() {
      return this.delegate.toString();
    }

  }

}
Predicate.test 방법(XxRoute Predicate Factory 의 apply 방법 으로 돌아 오 는 Gateway Predicate)을 호출 합 니 다.
Gateway Predicate.test 를 호출 하여 현재 요청 한 경로 가 일치 하 는 지 판단 합 니 다.
전체 프로 세 스:
1.시스템 은 모든 Predicate(술어)와 Filter(필터)를 초기 화 합 니 다.
2.설 정 된 경로 정보(필터,술어)에 따라 경로 대상 을 되 돌려 줍 니 다.
3.요청 경로 에 따라 일치 하 는 경로 찾기
이상!!!
스프링 클 라 우 드 게 이 트 웨 이 경로 설정 포 지 셔 닝 원리 분석 에 관 한 글 은 여기까지 입 니 다.스프링 클 라 우 드 게 이 트 웨 이 원리 분석 내용 에 대해 서 는 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기