一. Gateway 网关基础与源码分析

一. 基础

推荐看别人整理的比较好的教程博客
推荐看别人整理的比较好的教程博客

  1. Gateway 简单介绍
  1. 底层使用的是Spring Boot和Spring Webflux提供的Netty底层环境
  2. Gateway 基于异步非阻塞模型性能较高
  3. 动态路由,能够匹配任何请求属性
  4. 可以对路由指定 Predicate 断言,和 Filter 过滤器
  5. 集成Hystrix断路器功能
  6. 集成 Spring Cloud 服务发现功能
  7. 支持请求限流功能,支持路径重写功能
    在这里插入图片描述
  1. Gateway 三大核心概念
  1. 路由 Route : 可以理解为设置请求转发到指定服务器的过程,构建网关的基本模块,由 ID, 目标 URI 一系列的断言和过滤器组成,如果断言为true 则匹配路由
  2. 断言 Predicate : 开发人员通过匹配 HTTP 请求中携带的内容,使用断言判断匹配
  3. 过滤 Filter : 值的是GatewayFilter过滤器,通过使用过滤器,对请求拦截,在请求路由前后作出指定操作
  1. 客户端发送请求到达 Gateway, 通过 HandlerMapping 处理器映射器找到与请求相匹配的路由,将其发送到指定的GatewayWebHandler(是不是SpringMVC 差不多的?controller 请求路径?),然后在路由请求前或后执行过滤器 GatewayFilter,实现流量监控,权限校验,日志输出,协议转换等功能,Gateway 核心就是路由转发+执行过滤链
    在这里插入图片描述
  2. Gateway 的 Filter 的生命周期不像 Zuul 的那么丰富,它只有两个:“pre” 和 “post”。

PRE: 这种过滤器在请求被路由之前调用。我们可利用这种过滤器实现身份验证、在集群中选择请求的微服务、记录调试信息等。
POST:这种过滤器在路由到微服务以后执行。这种过滤器可用来为响应添加标准的 HTTP Header、收集统计信息和指标、将响应从微服务发送给客户端等。

  1. Gateway 的 Filter 从作用范围可分为另外两种GatewayFilter 与 GlobalFilter。

GatewayFilter:应用到单个路由或者一个分组的路由上。
GlobalFilter:应用到所有的路由上。

  1. SpringCloudGateway与WebFlux与Netty三者之间有什么关系: SpringCloudGateway使用了WebFlux作为web层框架,WebFlux又使用了Reactor Netty作为底层的网络编程框架,Reactor Netty又是基于Netty的异步事件驱动的网络应用框架
  1. SpringCloudGateway:提供了路由,过滤,限流,熔断等API网关的功能,可以对微服务进行统一的管理和保护
  2. WebFlux:提供了响应式编程的支持,可以处理异步和流式的数据,提供了基于注解和函数式的两种编程模型
  3. Reactor Netty:提供了非阻塞和反压支持的TCP, HTTP, 和UDP客户端和服务器,可以充分利用CPU资源,避免频繁的线程切换和阻塞,提高并发处理能力
  4. Netty:提供了一个高性能的网络编程框架,支持多种协议和传输层,提供了零拷贝,内存池,序列化等优化技术
  1. Netty为什么性能高
  1. netty采用了IO多路复用技术,多个IO的阻塞复用到一个select线程阻塞上,能够有效的应对大量的并发请求
  2. 基于多路复用Reactor线程模型,将服务端监听线程和IO线程分离,使用NioEventLoop来表示一个不断循环执行处理任务的线程,每个NioEventLoop有一个selector,用于监听绑定在其上的socket链路,可以充分利用CPU资源,减少线程切换与阻塞
  3. netty采用了无锁化串行设计,即消息的处理尽可能在一个线程内完成,期间不进行线程切换,避免了多线程竞争和同步锁的使用。同时通过调整NioEventLoopGroup的线程参数,可以同时启动多个串行化的线程并行运行,提升性能。
  4. netty内部使用了大量的比如volatile,CAS和原子类等兼顾性能的情况下提供并发安全的支持
  5. netty采用了高性能的序列化框架,默认提供了对Google Protobuf的支持,Protobuf序列化后的码流只有Java序列化的1/4左右,节省了网络带宽和CPU资源。
  6. netty采用了零拷贝技术,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二次拷贝,同时提供了组合Buffer对象,可以聚合多个ByteBuffer对象,避免了内存拷贝,还使用了transferTo方法,可以直接将文件缓冲区的数据发送到目标Channel
  7. netty采用了内存池技术,可以重用ByteBuf对象,内部维护了一个内存池,提升内存的使用效率,降低GC
  8. netty提供了灵活的TCP参数配置能力,可以根据不同的场景合理设置TCP参数,例如SO_RCVBUF, SO_SNDBUF,SO_TCPNODELAY等,这些参数对于性能的影响是非常大的

二. Gateway 底层源码解析

  1. 引入gateway依赖后,启动Gateway 网关服务自动加载的类,通过启动加载步骤,了解 Gaterway 网关服务的初始化
    在这里插入图片描述

1. GatewayClassPathWarningAutoConfiguration 判断引入的依赖

  1. 首先会加载 GatewayClassPathWarningAutoConfiguration ,查看该类源码
package org.springframework.cloud.gateway.config;

@Configuration(
    proxyBeanMethods = false
)
@AutoConfigureBefore({GatewayAutoConfiguration.class})
public class GatewayClassPathWarningAutoConfiguration {
    private static final Log log = LogFactory.getLog(GatewayClassPathWarningAutoConfiguration.class);
    private static final String BORDER = "\n\n**********************************************************\n\n";

    public GatewayClassPathWarningAutoConfiguration() {
    }

	//1.判断当前网关服务项目是否引入依赖了 DispatcherHandler,如果没有则抛出异常
	//也就是 Gateway 基于 Spring Webflux 使用 DispatcherHandler 接收用户请求 需要引入
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnMissingClass({"org.springframework.web.reactive.DispatcherHandler"})
    protected static class WebfluxMissingFromClasspathConfiguration {
        public WebfluxMissingFromClasspathConfiguration() {
            GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************\n\nSpring Webflux is missing from the classpath, which is required for Spring Cloud Gateway at this time. Please add spring-boot-starter-webflux dependency.\n\n**********************************************************\n\n");
        }
    }

	//2.判断当前网关服务是否引入依赖了 DispatcherServlet ,由于 Gateway 使用的是 DispatcherHandler
	//如果引入依赖了 DispatcherServlet 则抛出异常,也就是当前服务项目中不可以添加 web 相关依赖
    @Configuration(
        proxyBeanMethods = false
    )
    @ConditionalOnClass(
        name = {"org.springframework.web.servlet.DispatcherServlet"}
    )
    protected static class SpringMvcFoundOnClasspathConfiguration {
        public SpringMvcFoundOnClasspathConfiguration() {
            GatewayClassPathWarningAutoConfiguration.log.warn("\n\n**********************************************************\n\nSpring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. Please remove spring-boot-starter-web dependency.\n\n**********************************************************\n\n");
        }
    }
}

2. GatewayAutoConfiguration 创建注入 Gateway 服务需要用到的 bean 到 Spring 容器中

  • 解析 yml 中定义的 Gateway 相关的配置信息,创建注入 GatewayProperties
  • 创建注入各种 PredicateFactory 工厂与 FilterFactory 工厂
  • 创建 PropertiesRouteDefinitionLocator 路由装载器,通过 GatewayProperties 实例获取 RouteDefinition 信息
  • 注意点: RouteDefinitionLocator 为装载器接口,针对路由信息存储位置不同,获取方式不同,实现该接口提供了不同的不同的路由装载器

PropertiesRouteDefinitionLocator 是以 解析 yml 或 prperties 方式读取解析
RouteDefinitionRepository 是以存储器( 例如,内存 / Redis / MySQL 等 )读取解析
DiscoveryClientRouteDefinitionLocator 是以注册中心( 例如,Eureka / Consul / Zookeeper / Etcd 等 )读
CompositeRouteDefinitionLocator ,组合多种 RouteDefinitionLocator 的实现,为 RouteDefinitionRouteLocator 提供统一入口,
详细可以参考大神的

  • 创建 CompositeRouteDefinitionLocator 路由装载器,主要作用就是将各个定位器合并提供统一的getRouteDefinitions方法入口,加载所有RouteDefinition
  • RouteDefinition 可以转换为 Route
  • 通过 GatewayProperties 创建路由定位器 RouteLocator ,通过路由定位器获取指定路由 Route
  • 初始化基于缓存的路由定位器 CachingRouteLocator,当第一次执行后会将路由信息存入map缓存中,后续通过缓存获取,并通过监听 RefreshRoutesEvent 事件刷新缓存的路由信息,详细参考大神的
	//初始化 RoutePredicateHandlerMapping 
 	@Bean
    public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties, Environment environment) {
        return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment);
    }
	//从appliccation.yml中解析加载Gateway相关的配置信息
 	@Bean
    public GatewayProperties gatewayProperties() {
        return new GatewayProperties();
    }
    //初始化 PropertiesRouteDefinitionLocator 路由装载器
	@Bean
    @ConditionalOnMissingBean
    public PropertiesRouteDefinitionLocator propertiesRouteDefinitionLocator(GatewayProperties properties) {
        return new PropertiesRouteDefinitionLocator(properties);
    }
	//初始化 CompositeRouteDefinitionLocator 路由装载器
	@Bean
    @Primary
    public RouteDefinitionLocator routeDefinitionLocator(List<RouteDefinitionLocator> routeDefinitionLocators) {
        return new CompositeRouteDefinitionLocator(Flux.fromIterable(routeDefinitionLocators));
    }
    
    //初始化路由定位器
    @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)));
    }

	//创建各种PredicateFactory
 	@Bean
    public PathRoutePredicateFactory pathRoutePredicateFactory() {
        return new PathRoutePredicateFactory();
    }
    @Bean
    public QueryRoutePredicateFactory queryRoutePredicateFactory() {
        return new QueryRoutePredicateFactory();
    }
    @Bean
    public ReadBodyPredicateFactory readBodyPredicateFactory() {
        return new ReadBodyPredicateFactory();
    }
    @Bean
    public RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory() {
        return new RemoteAddrRoutePredicateFactory();
    }
    @Bean
    @DependsOn({"weightCalculatorWebFilter"})
    public WeightRoutePredicateFactory weightRoutePredicateFactory() {
        return new WeightRoutePredicateFactory();
    }
    @Bean
    public CloudFoundryRouteServiceRoutePredicateFactory cloudFoundryRouteServiceRoutePredicateFactory() {
        return new CloudFoundryRouteServiceRoutePredicateFactory();
    }
    
	//创建各种 FilterFactory
	@Bean
    public AddRequestHeaderGatewayFilterFactory addRequestHeaderGatewayFilterFactory() {
        return new AddRequestHeaderGatewayFilterFactory();
    }
    @Bean
    public MapRequestHeaderGatewayFilterFactory mapRequestHeaderGatewayFilterFactory() {
        return new MapRequestHeaderGatewayFilterFactory();
    }
    @Bean
    public AddRequestParameterGatewayFilterFactory addRequestParameterGatewayFilterFactory() {
        return new AddRequestParameterGatewayFilterFactory();
    }
    @Bean
    public AddResponseHeaderGatewayFilterFactory addResponseHeaderGatewayFilterFactory() {
        return new AddResponseHeaderGatewayFilterFactory();
    }
    @Bean
    public ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory() {
        return new ModifyRequestBodyGatewayFilterFactory();
    }
    @Bean
    public DedupeResponseHeaderGatewayFilterFactory dedupeResponseHeaderGatewayFilterFactory() {
        return new DedupeResponseHeaderGatewayFilterFactory();
    }
    @Bean
    public ModifyResponseBodyGatewayFilterFactory modifyResponseBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) {
        return new ModifyResponseBodyGatewayFilterFactory(codecConfigurer);
    }
    @Bean
    public PrefixPathGatewayFilterFactory prefixPathGatewayFilterFactory() {
        return new PrefixPathGatewayFilterFactory();
    }
    @Bean
    public PreserveHostHeaderGatewayFilterFactory preserveHostHeaderGatewayFilterFactory() {
        return new PreserveHostHeaderGatewayFilterFactory();
    }
    @Bean
    public RedirectToGatewayFilterFactory redirectToGatewayFilterFactory() {
        return new RedirectToGatewayFilterFactory();
    }
    @Bean
    public RemoveRequestHeaderGatewayFilterFactory removeRequestHeaderGatewayFilterFactory() {
        return new RemoveRequestHeaderGatewayFilterFactory();
    }
    @Bean
    public RemoveRequestParameterGatewayFilterFactory removeRequestParameterGatewayFilterFactory() {
        return new RemoveRequestParameterGatewayFilterFactory();
    }
    @Bean
    public RemoveResponseHeaderGatewayFilterFactory removeResponseHeaderGatewayFilterFactory() {
        return new RemoveResponseHeaderGatewayFilterFactory();
    }
    

GatewayProperties

//网关配置信息加载 从appliccation.yml中解析前缀为spring.cloud.gateway的配置
@ConfigurationProperties("spring.cloud.gateway")
@Validated
public class GatewayProperties {
    //路由定义列表,加载配置key=spring.cloud.gateway.routes 列表
    private List<RouteDefinition> routes = new ArrayList<>();
    //默认的过滤器定义列表,加载配置 key = spring.cloud.gateway.default-filters 列表
    private List<FilterDefinition> defaultFilters = new ArrayList<>();
   //网媒体类型列表,加载配置 key = spring.cloud.gateway.streamingMediaTypes 列表
   //默认包含{text/event-stream,application/stream+json}
    private List<MediaType> streamingMediaTypes = Arrays.asList(MediaType.TEXT_EVENT_STREAM,MediaType.APPLICATION_STREAM_JSON);
}           

3. GatewayLoadBalancerClientAutoConfiguration 创建 LoadBalancerClientFilter 过滤器,通过该过滤器在网关执行时实现负载均衡

package org.springframework.cloud.gateway.config;

@Configuration(
    proxyBeanMethods = false
)
@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class})
@AutoConfigureAfter({RibbonAutoConfiguration.class})
@EnableConfigurationProperties({LoadBalancerProperties.class})
public class GatewayLoadBalancerClientAutoConfiguration {
    public GatewayLoadBalancerClientAutoConfiguration() {
    }

    @Bean
    @ConditionalOnBean({LoadBalancerClient.class})
    @ConditionalOnMissingBean({LoadBalancerClientFilter.class, ReactiveLoadBalancerClientFilter.class})
    public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client, LoadBalancerProperties properties) {
    	//创建 LoadBalancerClientFilter 过滤器注入到容器中
        return new LoadBalancerClientFilter(client, properties);
    }
}

LoadBalancerClientFilter 过滤器源码, 该类实现了 GlobalFilter 与 Ordered 接口,说明该类是一个全局过滤器,当 Gateway 接收到请求时会自动执行该过滤器中的 filter() 方法进行拦截过滤(可以根据该过滤器模拟实现自定义过滤器)

package org.springframework.cloud.gateway.filter;

/** @deprecated */
@Deprecated
public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
    public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100;
    private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class);
    protected final LoadBalancerClient loadBalancer;
    private LoadBalancerProperties properties;

    public LoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
        this.loadBalancer = loadBalancer;
        this.properties = properties;
    }

    public int getOrder() {
        return 10100;
    }

    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    	//1.以 yml 方式配置为例,当前url 读取到的就是 yml 中配置的  
    	//假设配置的uri为: "uri: lb://cloud-payment-service" 
        URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
        //2.如果配置的 uri 中有"lb",则使用负载
        if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
        	//3.将 "lb://cloud-payment-service" 替换为 http://IP:PORT/path 路径的url
            ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
            if (log.isTraceEnabled()) {
                log.trace("LoadBalancerClientFilter url before: " + url);
            }
			//4.负载,获取指定的服务实例 ServiceInstance (是通过 DiscoveryClient 获取到的)
            ServiceInstance instance = this.choose(exchange);
            if (instance == null) {
                throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
            } else {
                URI uri = exchange.getRequest().getURI();
                String overrideScheme = instance.isSecure() ? "https" : "http";
                if (schemePrefix != null) {
                    overrideScheme = url.getScheme();
                }
				//5.通过 ServiceInstance 服务实例,此处拿到的就是真实的服务调用地址
                URI requestUrl = this.loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri);
                if (log.isTraceEnabled()) {
                    log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
                }

                exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
                //5.继续执行下一个过滤器
                return chain.filter(exchange);
            }
        } else {
        	//如果没有lb 则不适用负载,直接执行下一个过滤器
            return chain.filter(exchange);
        }
    }

    protected ServiceInstance choose(ServerWebExchange exchange) {
        return this.loadBalancer.choose(((URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR)).getHost());
    }
}

4. GatewayRedisAutoConfiguration 网关服务与 Redis

Gateway + redis+ lua 可以实现网关限流功能

三. Gateway 接收请求 DispatcherHandler 中执行请求 handle() 方法主要步骤

当发送请求时会将请求参数封装为 ServerWebExchange ,执行 handle() 方法,DispatcherHandler 中包含了, List handlerMappings , List handlerAdapters 适配器, List resultHandlers 处理器,initStrategies()是初始化方法

	//初始化方法
	protected void initStrategies(ApplicationContext context) {
        Map<String, HandlerMapping> mappingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerMapping.class, true, false);
        ArrayList<HandlerMapping> mappings = new ArrayList(mappingBeans.values());
        AnnotationAwareOrderComparator.sort(mappings);
        this.handlerMappings = Collections.unmodifiableList(mappings);
        Map<String, HandlerAdapter> adapterBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerAdapter.class, true, false);
        this.handlerAdapters = new ArrayList(adapterBeans.values());
        AnnotationAwareOrderComparator.sort(this.handlerAdapters);
        Map<String, HandlerResultHandler> beans = BeanFactoryUtils.beansOfTypeIncludingAncestors(context, HandlerResultHandler.class, true, false);
        this.resultHandlers = new ArrayList(beans.values());
        AnnotationAwareOrderComparator.sort(this.resultHandlers);
    }

	//接收请求执行方法, ServerWebExchange 中保存了接收到的请求的所有信息
    public Mono<Void> handle(ServerWebExchange exchange) {
        return this.handlerMappings == null ? this.createNotFoundError() : Flux.fromIterable(this.handlerMappings)
		
		.concatMap((mapping) -> {
			//1.遍历初始化时创建的 handlerMappings,通过接收到的用户请求 ServerWebExchange 数据获取到指定的 handler
            return mapping.getHandler(exchange);
        }).next().switchIfEmpty(this.createNotFoundError()).flatMap((handler) -> {
        	//2.调用 invokeHandler() 方法执行 handler
            return this.invokeHandler(exchange, handler);
        }).flatMap((result) -> {
        	//3.封装结果集响应
            return this.handleResult(exchange, result);
        });
    }

1. mapping.getHandler() 通过 HandlerMapping 获取 Handler

在AbstractHandlerMapping 抽象类中

public Mono<Object> getHandler(ServerWebExchange exchange) {
		//调用 RoutePredicateHandlerMapping 中的 getHandlerInternal() 方法
        return this.getHandlerInternal(exchange).map((handler) -> {
            if (this.logger.isDebugEnabled()) {
                this.logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
            }

            if (this.hasCorsConfigurationSource(handler)) {
                ServerHttpRequest request = exchange.getRequest();
                CorsConfiguration config = this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(exchange) : null;
                CorsConfiguration handlerConfig = this.getCorsConfiguration(handler, exchange);
                config = config != null ? config.combine(handlerConfig) : handlerConfig;
                if (!this.corsProcessor.process(config, exchange) || CorsUtils.isPreFlightRequest(request)) {
                    return REQUEST_HANDLED_HANDLER;
                }
            }

            return handler;
        });
    }

RoutePredicateHandlerMapping 中的 getHandlerInternal() 方法

protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
        if (this.managementPortType == RoutePredicateHandlerMapping.ManagementPortType.DIFFERENT && this.managementPort != null && exchange.getRequest().getURI().getPort() == this.managementPort) {
            return Mono.empty();
        } else {
            exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_HANDLER_MAPPER_ATTR, this.getSimpleName());
            //通过 exchange 查找对应的路由策略(也就是通过路由id查找到分组路由)
            return this.lookupRoute(exchange).flatMap((r) -> {
                exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR);
                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Mapping [" + this.getExchangeDesc(exchange) + "] to " + r);
                }

                exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR, r);
                return Mono.just(this.webHandler);
            }).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
                exchange.getAttributes().remove(ServerWebExchangeUtils.GATEWAY_PREDICATE_ROUTE_ATTR);
                if (this.logger.isTraceEnabled()) {
                    this.logger.trace("No RouteDefinition found for [" + this.getExchangeDesc(exchange) + "]");
                }

            })));
        }
    }

lookupRoute() 该方法返回了一个 Route

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

            this.validateRoute(route, exchange);
            return route;
        });
    }

查看 Route,Route 中的数据是通过 yml 或配置类方式进行配置的 Gateway 路由规则,路由到的实际服务器地址等等,该数据在服务启动时已经通过

public class Route implements Ordered {
    private final String id;  //路由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;
}

2. this.invokeHandler() 执行 Handler

DispatcherHandler 中获取到 Handler 后执行的 invokeHandler 方法, 方法内通过 handlerAdapter 适配器调用 handle() 方法执行(默认调用 SimpleHandlerAdapter 中的 handle() 方法)

	//handle() 中获取到 Handler 后执行的 invokeHandler() 方法
	private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
        if (this.handlerAdapters != null) {
            Iterator var3 = this.handlerAdapters.iterator();

            while(var3.hasNext()) {
                HandlerAdapter handlerAdapter = (HandlerAdapter)var3.next();
                if (handlerAdapter.supports(handler)) {
                	//执行handler
                    return handlerAdapter.handle(exchange, handler);
                }
            }
        }

        return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
    }

SimpleHandlerAdapter 中的 handle() 方法,该方法中执行 webHandler.handle() 方(FilteringWebHandler 中的 handle() 方法)

	public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
        WebHandler webHandler = (WebHandler)handler;
        Mono<Void> mono = webHandler.handle(exchange);
        return mono.then(Mono.empty());
    }

FilteringWebHandler 中的 handle() 方法,获取所有 GatewayFilter 过滤器,根据过滤器中配置的 Order 值遍历执行过滤器

	public Mono<Void> handle(ServerWebExchange exchange) {
        Route route = (Route)exchange.getRequiredAttribute(ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR);
        //获取到所有 GatewayFilter 过滤器
        List<GatewayFilter> gatewayFilters = route.getFilters();
        List<GatewayFilter> combined = new ArrayList(this.globalFilters);
        //放入集合中
        combined.addAll(gatewayFilters);
        AnnotationAwareOrderComparator.sort(combined); 
        if (logger.isDebugEnabled()) {
            logger.debug("Sorted gatewayFilterFactories: " + combined);
        }
		//遍历执行 Filter
        return (new FilteringWebHandler.DefaultGatewayFilterChain(combined)).filter(exchange);
    }

默认获取到8个 GatewayFilter,在执行到 LoadBalancerClientFilter 过滤器时,根据配置的 uri 选择负载策略,将uri转换为真实的服务器地址,获取服务实例 ServiceInstance
在这里插入图片描述
最终 过滤器执行完毕,调用服务,将请求代理到指定的服务器上,执行DispatcherHandler 中的 this.handleResult() 封装返回结果集

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值