preface
Record the Spring Cloud Gateway from the dimensions of routelocator, routedefinitionlocator, filteringwebhandler and related assembly classes
RouteLocator
public interface RouteLocator { Flux<Route> getRoutes(); }
The Route positioning class is generally configured with Spring Cloud Gateway. We will also construct the corresponding RouteLocator based on RouteLocatorBuilder, such as:
@Bean public RouteLocator routeLocator(RouteLocatorBuilder builder) { return builder.routes() .route(p -> p .path("/client1/{segment}") .filters(f -> f.stripPrefix(1)) .uri("http://localhost:8801/") ) .build(); }
Of course, it supports multi group route collection:
CachingRouteLocator
Cache the internal RouteLocator and refresh based on events
CompositeRouteLocator
Combination: combine multiple groups of routelocators into one
RouteDefinitionRouteLocator
@Override public Flux<Route> getRoutes() { /** * Get all routedefinitions based on routedefinionlocator * Convert to Route instance */ Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions().map(this::convertToRoute); // ... return routes.map(route -> { if (logger.isDebugEnabled()) { logger.debug("RouteDefinition matched: " + route.getId()); } return route; }); }
- Obtain all routedefinitions based on routedefinionlocator and convert them into Route instances
- It can be seen that only this class and the anonymous instance constructed based on RouteLocatorBuilder in the configuration class mentioned earlier are really responsible for route resolution
Assembly class GatewayAutoConfiguration
@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) { /** * Combine all RouteLocator instances and cache */ return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators))); }
In the automatic assembly class GatewayAutoConfiguration:
- RouteDefinitionRouteLocator instance registered
- Collect all RouteLocator instances in the container (actually the two described above), Composite and Caching, and register the cacheingroutelocator instance
- Because of the @ Primary annotation, the cachedCompositeRouteLocator instance is mainly used in the container later
RouteDefinitionLocator
public interface RouteDefinitionLocator { Flux<RouteDefinition> getRouteDefinitions(); }
- As mentioned earlier, RouteDefinitionRouteLocator obtains all routedefinitions based on routeDefinitionLocator and converts them into Route instances
- RouteDefinitionLocator, a Route definition locator, is used to collect multiple groups of routedefinitions, which are finally handed over to RouteDefinitionRouteLocator and converted into Route
CachingRouteDefinitionLocator
Cache the internal RouteDefinitionLocator and refresh based on events
CompositeRouteDefinitionLocator
It combines a set of routedefinitionlocators, so the getRouteDefinitions method emits all RouteDefinition elements
InMemoryRouteDefinitionRepository
Based on a set of routedefinitions for memory management, the save delete method is provided. By default, an instance is provided in the automatic assembly class, which can be overwritten by itself, as follows:
@Bean public RouteDefinitionRepository repository() { PredicateDefinition predicateDefinition = new PredicateDefinition("Path=/eureka-client/{segement}"); FilterDefinition filterDefinition = new FilterDefinition("StripPrefix=1"); RouteDefinition routeDefinition = new RouteDefinition(); routeDefinition.setId("test-repo"); routeDefinition.setPredicates(Arrays.asList(new PredicateDefinition[] { predicateDefinition })); routeDefinition.setFilters(Arrays.asList(new FilterDefinition[] { filterDefinition })); routeDefinition.setUri(URI.create("http://localhost:8801")); InMemoryRouteDefinitionRepository repository = new InMemoryRouteDefinitionRepository(); Mono<RouteDefinition> route = Mono.fromSupplier(() -> routeDefinition); // You must subscribe here. I don't know the reason @ TODO repository.save(route).subscribe(); return repository; }
PropertiesRouteDefinitionLocator
private final GatewayProperties properties; @Override public Flux<RouteDefinition> getRouteDefinitions() { return Flux.fromIterable(this.properties.getRoutes()); }
Obtaining based on GatewayProperties is actually reading based on the configuration file, similar to:
spring: application: name: gateway cloud: gateway: discovery: locator: enabled: true routes: - id: test uri: http://localhost:8801 predicates: - Path=/client/{segement} filters: - StripPrefix=1
DiscoveryClientRouteDefinitionLocator
This class generates a default RouteDefinition for each service based on service discovery, matches the route based on pathroutepredictefactory, and rewrites the path as lb:// + serviceId based on RewritePathGatewayFilterFactory
Assembly class
GatewayAutoConfiguration
@Bean @ConditionalOnMissingBean public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) { return new PropertiesRouteDefinitionLocator(properties); } @Bean @ConditionalOnMissingBean(RouteDefinitionRepository.class) public InMemoryRouteDefinitionRepository inMemoryRouteDefinitionRepository() { return new InMemoryRouteDefinitionRepository(); } @Bean @Primary public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) { return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators)); }
- Register PropertiesRouteDefinitionLocator based on profile resolution
- Register memory management based InMemoryRouteDefinitionRepository
- CompositeRouteDefinitionLocator manages all of the above routedefinitionlocators, marked @ Primary, and can be directly injected into the container
GatewayDiscoveryClientAutoConfiguration
@Bean public DiscoveryLocatorProperties discoveryLocatorProperties() { DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties(); properties.setPredicates(initPredicates()); properties.setFilters(initFilters()); return properties; } @Configuration(proxyBeanMethods = false) @ConditionalOnProperty(value = "spring.cloud.discovery.reactive.enabled", matchIfMissing = true) public static class ReactiveDiscoveryClientRouteDefinitionLocatorConfiguration { @Bean @ConditionalOnProperty(name = "spring.cloud.gateway.discovery.locator.enabled") public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator( ReactiveDiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) { return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties); } }
- The configuration service finds the default route matcher and filter, that is, the pathroutepredictefactory and RewritePathGatewayFilterFactory mentioned earlier
- Register the DiscoveryClientRouteDefinitionLocator instance based on the configuration item spring cloud. gateway. discovery. locator. enabled=true
FilteringWebHandler
@Override public Mono<Void> handle(ServerWebExchange exchange) { Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR); /** * Obtain interceptors from the route instance, including default filters */ List<GatewayFilter> gatewayFilters = route.getFilters(); /** * Then add globalFilters */ List<GatewayFilter> combined = new ArrayList<>(this.globalFilters); combined.addAll(gatewayFilters); // Sorting based on Order interface AnnotationAwareOrderComparator.sort(combined); if (logger.isDebugEnabled()) { logger.debug("Sorted gatewayFilterFactories: " + combined); } // Intercept operation return new DefaultGatewayFilterChain(combined).filter(exchange); }
- All filters in the Route instance will be obtained here, including default filters (specified in the configuration file, configuration item spring. Cloud. Gateway. Default filters)
- It will also add globalFilters in all containers. Many are registered in the assembly class by default, omitted
- Finally, intercept
Assembly class GatewayAutoConfiguration
@Bean public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) { return new FilteringWebHandler(globalFilters); }
summary
Relevant records of Spring Cloud Gateway source code reading