乐趣区

关于java:gateway-启动

咱们从 spring.factories 开始,次要是 GatewayAutoConfiguration,这里次要加载 CompositeRouteDefinitionLocator、RouteDefinitionRouteLocator、FilteringWebHandler、RoutePredicateHandlerMapping、RouteRefreshListener、CachingRouteLocator 等。
RouteLocator 和 RouteDefinitionLocator 的作用在上一篇曾经提过了,FilteringWebHandler、RoutePredicateHandlerMapping 这两个等调用的时候讲,这边先晓得他们会在这里加载。咱们次要看看 RouteRefreshListener 和 CachingRouteLocator。

RouteRefreshListener

RouteRefreshListener 实现了 ApplicationListener 接口,所以他会调用 onApplicationEvent 办法,在合乎某些条件下,会调用 reset 办法,这个思路和 zuul 是一样的。所以动静的刷新也能够调用他的事件来触发。

public void onApplicationEvent(ApplicationEvent event) {
    if (event instanceof ContextRefreshedEvent
            || event instanceof RefreshScopeRefreshedEvent
            || event instanceof InstanceRegisteredEvent) {reset();
    }
    else if (event instanceof ParentHeartbeatEvent) {ParentHeartbeatEvent e = (ParentHeartbeatEvent) event;
        resetIfNeeded(e.getValue());
    }
    else if (event instanceof HeartbeatEvent) {HeartbeatEvent e = (HeartbeatEvent) event;
        resetIfNeeded(e.getValue());
    }
}

咱们看看 reset 办法,他其实就是公布了一个 RefreshRoutesEvent 事件。

private void reset() {this.publisher.publishEvent(new RefreshRoutesEvent(this));
}

CachingRouteLocator

CachingRouteLocator 就是用来接管 RefreshRoutesEvent 事件的,他实现了 ApplicationListener<RefreshRoutesEvent> 接口。咱们看看他的 onApplicationEvent 办法。

public void onApplicationEvent(RefreshRoutesEvent event) {
    try {fetch().collect(Collectors.toList()).subscribe(list -> Flux.fromIterable(list)
                .materialize().collect(Collectors.toList()).subscribe(signals -> {
                    applicationEventPublisher
                            .publishEvent(new RefreshRoutesResultEvent(this));
                    cache.put(CACHE_KEY, signals);
                }, throwable -> handleRefreshError(throwable)));
    }
    catch (Throwable e) {handleRefreshError(e);
    }
}

他先会调用 fetch 办法,这里实际上就是调用 CompositeRouteLocator#getRoutes,最初再调用 RouteDefinitionRouteLocator#getRoutes。

private Flux<Route> fetch() {return this.delegate.getRoutes().sort(AnnotationAwareOrderComparator.INSTANCE);
}

RouteDefinitionRouteLocator#getRoutes

这个办法能够看到他是获取 RouteDefinition 的汇合,而后再调用 convertToRoute 办法,在这个办法里,把 RouteDefinition 转为 Route。

@Override
public Flux<Route> getRoutes() {Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
            .map(this::convertToRoute);

    // 其余略
}

RouteDefinitionRouteLocator#convertToRoute

在这里把 RouteDefinition 转为 Route,次要是解析 Predicate 和 GatewayFilter,咱们在上一篇曾经晓得了他会通过工厂类来解决。combinePredicates 办法就是解决 Predicate 的,getFilters 是解决 Filter 的。

private Route convertToRoute(RouteDefinition routeDefinition) {AsyncPredicate<ServerWebExchange> predicate = combinePredicates(routeDefinition);
    List<GatewayFilter> gatewayFilters = getFilters(routeDefinition);

    return Route.async(routeDefinition).asyncPredicate(predicate)
            .replaceFilters(gatewayFilters).build();}

RouteDefinitionRouteLocator#combinePredicates

在这里就是把 RouteDefinition 的 predicate 转为 Route 须要的 Predicate。这里首先会创立一个 Predicate,而后再把残余的合并,造成了一个 left、right 的构造。结构图在上一篇曾经说过了。
lookup 办法就是通过工厂类创立 Predicate 的中央。

private AsyncPredicate<ServerWebExchange> combinePredicates(RouteDefinition routeDefinition) {List<PredicateDefinition> predicates = routeDefinition.getPredicates();
    if (predicates == null || predicates.isEmpty()) {
        // this is a very rare case, but possible, just match all
        return AsyncPredicate.from(exchange -> true);
    }
    // 创立第一个 Predicate
    AsyncPredicate<ServerWebExchange> predicate = lookup(routeDefinition,
            predicates.get(0));
    // 把残余的进行合并
    for (PredicateDefinition andPredicate : predicates.subList(1,
            predicates.size())) {
        AsyncPredicate<ServerWebExchange> found = lookup(routeDefinition,
                andPredicate);
        predicate = predicate.and(found);
    }

    return predicate;
}

RouteDefinitionRouteLocator#lookup

这个办法里,首先先通过配置的名称,获取对应的 RoutePredicateFactory,而后组装 config 信息,最初通过 factory.applyAsync 创立 Predicate。

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());
    }
    if (logger.isDebugEnabled()) {logger.debug("RouteDefinition" + route.getId() + "applying"
                + predicate.getArgs() + "to" + predicate.getName());
    }

    // @formatter:off
    Object config = this.configurationService.with(factory)
            .name(predicate.getName())
            .properties(predicate.getArgs())
            .eventFunction((bound, properties) -> new PredicateArgsEvent(RouteDefinitionRouteLocator.this, route.getId(), properties))
            .bind();
    // @formatter:on

    return factory.applyAsync(config);
}

RouteDefinitionRouteLocator#getFilters

这个是解决 Filter 的中央,他次要是通过 loadGatewayFilters 办法来获取对应的 Filter。

private List<GatewayFilter> getFilters(RouteDefinition routeDefinition) {List<GatewayFilter> filters = new ArrayList<>();

    // TODO: support option to apply defaults after route specific filters?
    if (!this.gatewayProperties.getDefaultFilters().isEmpty()) {
        filters.addAll(loadGatewayFilters(DEFAULT_FILTERS,
                new ArrayList<>(this.gatewayProperties.getDefaultFilters())));
    }

    if (!routeDefinition.getFilters().isEmpty()) {filters.addAll(loadGatewayFilters(routeDefinition.getId(),
                new ArrayList<>(routeDefinition.getFilters())));
    }

    AnnotationAwareOrderComparator.sort(filters);
    return filters;
}

RouteDefinitionRouteLocator#loadGatewayFilters

这个设计形式跟下面相似,也是通过配置信息的名称,获取对应的 GatewayFilterFactory,而后封装 configuration 信息,通过 factory.apply 创立一个 Filter。

List<GatewayFilter> loadGatewayFilters(String id,
        List<FilterDefinition> filterDefinitions) {ArrayList<GatewayFilter> ordered = new ArrayList<>(filterDefinitions.size());
    for (int i = 0; i < filterDefinitions.size(); i++) {FilterDefinition definition = filterDefinitions.get(i);
        GatewayFilterFactory factory = this.gatewayFilterFactories
                .get(definition.getName());
        if (factory == null) {
            throw new IllegalArgumentException(
                    "Unable to find GatewayFilterFactory with name"
                            + definition.getName());
        }
        if (logger.isDebugEnabled()) {
            logger.debug("RouteDefinition" + id + "applying filter"
                    + definition.getArgs() + "to" + definition.getName());
        }

        // @formatter:off
        Object configuration = this.configurationService.with(factory)
                .name(definition.getName())
                .properties(definition.getArgs())
                .eventFunction((bound, properties) -> new FilterArgsEvent(
                        // TODO: why explicit cast needed or java compile fails
                        RouteDefinitionRouteLocator.this, id, (Map<String, Object>) properties))
                .bind();
        // @formatter:on

        // some filters require routeId
        // TODO: is there a better place to apply this?
        if (configuration instanceof HasRouteId) {HasRouteId hasRouteId = (HasRouteId) configuration;
            hasRouteId.setRouteId(id);
        }

        GatewayFilter gatewayFilter = factory.apply(configuration);
        if (gatewayFilter instanceof Ordered) {ordered.add(gatewayFilter);
        }
        else {ordered.add(new OrderedGatewayFilter(gatewayFilter, i + 1));
        }
    }

    return ordered;
}

整体流程

退出移动版