Gateway源码分析

在微服务架构中,Spring Cloud Gateway属于流量管控核心枢纽。分析源码了解执行原理,可以洞察动态路由、过滤器链、异步响应等底层机制与设计巧思,掌握请求生命周期管理与高性能实现逻辑。能够帮助开发者优化路由策略、定制扩展功能,解决疑难问题,提升系统性能与可维护性。

01 工作原理

客户端向Spring Cloud Gateway发出请求,如果请求与网关路由匹配,则请求就会被发送到网关Web处理程序,此时处理程序运行特定请求过滤器链。

过滤器之间使用虚线分开原因是过滤器可能会在发送代理请求前后执行逻辑。所有前置(pre)过滤器逻辑先执行,然后执行代理请求。代理请求完成后,再执行后置(post)过滤器逻辑。

Spring Cloud Gateway(SCG)中lb 协议前缀底层使用Spring Cloud LoadBalancer作为负载均衡器。SCG默认集成LoadBalancer,无需额外配置即可实现服务间负载均衡调用。

02 Spring WebFlux

Spring Cloud Gateway基于WebFlux构建,与传统Servlet容器不同,Spring WebFlux可以运行在支持响应式编程服务器上,如Netty、Undertow等。

处理流程 处理细节
请求接收 当外部请求到达服务器,服务器封装请求为ServerHttpRequest对象,并且传递给Spring WebFlux DispatcherHandler进行分发处理。
请求映射 DispatcherHandler属于Spring WebFlux核心请求分发器,根据请求信息(如请求路径、请求方法等)通过HandlerMapping组件找到对应处理器(控制器方法)。
处理器调用 找到处理器后,DispatcherHandler调用HandlerAdapter执行处理器方法。处理器方法如果返回Mono或Flux类型对象,就表示异步处理结果。
过滤器链处理 Spring WebFlux使用过滤器链(WebFilter)预处理和后处理请求,然后额外添加日志记录、权限验证、请求参数修改等操作。
响应处理 DispatcherHandler调用处理器方法返回Mono或Flux对象,接下来就会使用结果处理器HandlerResultHandler处理响应值,封装ServerHttpResponse对象发送给客户端。

通过Spring WebFlux实现原理分析,Spring Cloud Gateway提供RoutePredicateHandlerMapping匹配路由映射规则,封装GatewayFilterChain进行过滤器链调用处理,以及使用NettyRoutingFilter接收外部请求进行客户端处理分发到目标服务。

java 复制代码
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    private List<HandlerMapping> handlerMappings;
    private List<HandlerAdapter> handlerAdapters;
    private List<HandlerResultHandler> resultHandlers;
    
    public DispatcherHandler(ApplicationContext applicationContext) {
        this.initStrategies(applicationContext);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.initStrategies(applicationContext);
    }

    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);
    }
}

03 自动装配

Gateway依赖spring-cloud-gateway-core.jar配置自动装配类GatewayAutoConfiguration和GatewayLoadBalancerClientAutoConfiguration,借助spring.factories文件实现配置发现和解析。

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\
org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\
org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration,\
...

3.1 网关配置

Gateway通过GatewayAutoConfiguration配置映射处理器(RoutePredicateHandlerMapping)、路由位置转换(RouteDefinitionRouteLocator),以及通过NettyConfiguration配置Netty客户端、全局路由过滤器(FilteringWebHandler)。

java 复制代码
@Configuration
@ConditionalOnProperty(name = "spring.cloud.gateway.enabled", matchIfMissing = true)
@EnableConfigurationProperties
@AutoConfigureBefore({HttpHandlerAutoConfiguration.class, WebFluxAutoConfiguration.class})
@AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class})
@ConditionalOnClass(DispatcherHandler.class)
public class GatewayAutoConfiguration {
    @Bean
    public GatewayProperties gatewayProperties() {
        return new GatewayProperties();
    }
    @Bean
    public RoutePredicateHandlerMapping routePredicateHandlerMapping(
        FilteringWebHandler webHandler, RouteLocator routeLocator,
        GlobalCorsProperties globalCorsProperties, Environment environment) {
        return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties, environment);
    }
    @Bean
    public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties,
        List<GatewayFilterFactory> gatewayFilters,
        List<RoutePredicateFactory> predicates,
        RouteDefinitionLocator routeDefinitionLocator,
        @Qualifier("webFluxConversionService") ConversionService conversionService) {
        return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, gatewayFilters, properties, conversionService);
    }
    @Bean
	public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) {
		return new FilteringWebHandler(globalFilters);
	}

    // 谓词: [...]RoutePredicateFactory
    // 过滤器: [...]GatewayFilterFactory
    @Configuration
    @ConditionalOnClass(HttpClient.class)
    protected static class NettyConfiguration {
        @Bean
        public HttpClientProperties httpClientProperties() {
            return new HttpClientProperties();
        }
        @Bean
        @ConditionalOnMissingBean
        public HttpClient gatewayHttpClient(HttpClientProperties properties) {
            HttpClientProperties.Pool pool = properties.getPool();
            // ...
            HttpClient httpClient = HttpClient.create(connectionProvider);
            // ...;

            return httpClient;
        }
        @Bean
        public NettyRoutingFilter routingFilter(HttpClient httpClient,
            ObjectProvider<List<HttpHeadersFilter>> headersFilters,
            HttpClientProperties properties) {
            return new NettyRoutingFilter(httpClient, headersFilters, properties);
        }
        @Bean
		public NettyWriteResponseFilter nettyWriteResponseFilter(GatewayProperties properties) {
			return new NettyWriteResponseFilter(properties.getStreamingMediaTypes());
		}
		@Bean
		public ReactorNettyWebSocketClient reactorNettyWebSocketClient(HttpClient httpClient) {
			return new ReactorNettyWebSocketClient(httpClient);
		}
    }
}

3.2 网关全局过滤器

java 复制代码
public class FilteringWebHandler implements WebHandler {
    private final List<GatewayFilter> globalFilters;
    
    public FilteringWebHandler(List<GlobalFilter> globalFilters) {
		this.globalFilters = loadFilters(globalFilters);
	}
    
    private static List<GatewayFilter> loadFilters(List<GlobalFilter> filters) {
		return filters.stream().map(filter -> {
			GatewayFilterAdapter gatewayFilter = new GatewayFilterAdapter(filter);
			if (filter instanceof Ordered) {
				int order = ((Ordered) filter).getOrder();
				return new OrderedGatewayFilter(gatewayFilter, order);
			}
			return gatewayFilter;
		}).collect(Collectors.toList());
	}
}

3.3 负载均衡过滤器

Gateway通过自动装配GatewayLoadBalancerClientAutoConfiguration配置负载均衡过滤器,实现配置lb路径进行负载均衡调用。

java 复制代码
@Configuration
@ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class })
@AutoConfigureAfter(RibbonAutoConfiguration.class)
@EnableConfigurationProperties(LoadBalancerProperties.class)
public class GatewayLoadBalancerClientAutoConfiguration {
	@Bean
	@ConditionalOnBean(LoadBalancerClient.class)
	@ConditionalOnMissingBean({ LoadBalancerClientFilter.class, ReactiveLoadBalancerClientFilter.class })
	public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client,
		LoadBalancerProperties properties) {
		return new LoadBalancerClientFilter(client, properties);
	}
}

3.4 处理适配器

Spring Boot依赖spring-boot-autoconfigure.jar自动配置WebFluxAutoConfiguration,配置类引入WebFlux关键核心组件。

properties 复制代码
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.reactive.WebFluxAutoConfiguration,\
...
java 复制代码
@ConditionalOnClass(WebFluxConfigurer.class)
@ConditionalOnMissingBean({ WebFluxConfigurationSupport.class })
@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class WebFluxAutoConfiguration {
	@Configuration
	@EnableConfigurationProperties({ ResourceProperties.class, WebFluxProperties.class })
	@Import({ EnableWebFluxConfiguration.class })
	public static class WebFluxConfig implements WebFluxConfigurer {
        //...
    }
    
    @Configuration
	public static class EnableWebFluxConfiguration extends DelegatingWebFluxConfiguration {
		// ....
	}
}
java 复制代码
public class DelegatingWebFluxConfiguration extends WebFluxConfigurationSupport {
    
}

public class WebFluxConfigurationSupport implements ApplicationContextAware {
    //...
    @Bean
	public HandlerFunctionAdapter handlerFunctionAdapter() {
		return new HandlerFunctionAdapter();
	}
	@Bean
	public SimpleHandlerAdapter simpleHandlerAdapter() {
		return new SimpleHandlerAdapter();
	}
}

04 处理请求

DispatcherHandler与DispatcherServlet相似,主要包括映射获取处理器(HandlerMapping)、处理器适配处理(HandlerAdapter)和结果处理器(HandlerResultHandler)三大核心接口。

java 复制代码
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange) {
        if (this.handlerMappings == null) {
			return createNotFoundError();
		}
		return Flux.fromIterable(this.handlerMappings)
                // 获取处理器
				.concatMap(mapping -> mapping.getHandler(exchange))
				.next()
				.switchIfEmpty(createNotFoundError())
                // 调用控制器方法
				.flatMap(handler -> invokeHandler(exchange, handler))
                // 结果处理
				.flatMap(result -> handleResult(exchange, result));
    }
}

4.1 获取处理器

Gateway通过RoutePredicateHandlerMapping进行路由谓词匹配,如果路由规则匹配就会缓存到请求上下文ServerWebExchange 属性GATEWAY_ROUTE_ATTR

java 复制代码
public abstract class AbstractHandlerMapping extends ApplicationObjectSupport implements HandlerMapping, Ordered, BeanNameAware {
    public Mono<Object> getHandler(ServerWebExchange exchange) {
        // 获取内部处理器
        return this.getHandlerInternal(exchange).map((handler) -> {
            // 跨域请求
            if (CorsUtils.isCorsRequest(exchange.getRequest())) {
                CorsConfiguration configA = this.corsConfigurationSource.getCorsConfiguration(exchange);
                CorsConfiguration configB = this.getCorsConfiguration(handler, exchange);
                CorsConfiguration config = configA != null ? configA.combine(configB) : configB;
                if (!this.getCorsProcessor().process(config, exchange) || CorsUtils.isPreFlightRequest(exchange.getRequest())) {
                    return REQUEST_HANDLED_HANDLER;
                }
            }
            return handler;
        });
    }
}
java 复制代码
public class RoutePredicateHandlerMapping extends AbstractHandlerMapping {
    @Override
	protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
		if (this.managementPortType == DIFFERENT && this.managementPort != null
				&& exchange.getRequest().getURI().getPort() == this.managementPort) {
			return Mono.empty();
		}
        // 网关处理程序映射程序属性名
		exchange.getAttributes().put(GATEWAY_HANDLER_MAPPER_ATTR, getSimpleName());

        // 匹配路由: 通过断言判断路由是否可用
		return lookupRoute(exchange)
				.flatMap((Function<Route, Mono<?>>) r -> {
                    // 网关谓词路由属性名
					exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
                    // 网关路由属性名
					exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
					return Mono.just(webHandler);
				}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
					exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
				})));
	}

    // 查找匹配得路由配置
    protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
        // 获取路由信息
		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);
            })
            .onErrorResume(e -> Mono.empty())
        )
        .next()
        .map(route -> {
            // 校验路由信息
            validateRoute(route, exchange);
            return route;
        });
	}
}

4.2 处理器方法调用

Gateway底层循环所有HandlerAdapter判断是否支持处理,如果支持就会调用HandlerAdapter#handle方法进行处理,网关主要处理方法就是SimpleHandlerAdapter。

java 复制代码
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
		if (this.handlerAdapters != null) {
			for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
                // 判断处理器是否支持
				if (handlerAdapter.supports(handler)) {
                    // 调用处理
					return handlerAdapter.handle(exchange, handler);
				}
			}
		}
		return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
	}
}
java 复制代码
public class SimpleHandlerAdapter implements HandlerAdapter {
	@Override
	public boolean supports(Object handler) {
		return WebHandler.class.isAssignableFrom(handler.getClass());
	}
    
	@Override
	public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
		WebHandler webHandler = (WebHandler) handler;
		Mono<Void> mono = webHandler.handle(exchange);
		return mono.then(Mono.empty());
	}
}

FilteringWebHandler内部就是获取路由配置的所有网关过滤器,然后进行调用链方式处理请求。

java 复制代码
package org.springframework.cloud.gateway.handler;

public class FilteringWebHandler implements WebHandler {
    @Override
	public Mono<Void> handle(ServerWebExchange exchange) {
        // 获取路由信息
		Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
        // 获取网关过滤器
		List<GatewayFilter> gatewayFilters = route.getFilters();

		List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
		combined.addAll(gatewayFilters);
		AnnotationAwareOrderComparator.sort(combined);

        // 过滤器调用
		return new DefaultGatewayFilterChain(combined).filter(exchange);
	}
}

4.3 负载均衡过滤器

LoadBalancerClientFilter属于全局过滤器,所以自动装配就会封装为GatewayFilterAdapter进行调用链循环处理。实际情况,需要具体版本查看具体是通过哪个负载均衡器进行处理。

java 复制代码
 public class FilteringWebHandler implements WebHandler {
     private static class DefaultGatewayFilterChain implements GatewayFilterChain {
		private final int index;
		private final List<GatewayFilter> filters;
		DefaultGatewayFilterChain(List<GatewayFilter> filters) {
			this.filters = filters;
			this.index = 0;
		}
		private DefaultGatewayFilterChain(DefaultGatewayFilterChain parent, int index) {
			this.filters = parent.getFilters();
			this.index = index;
		}
		@Override
		public Mono<Void> filter(ServerWebExchange exchange) {
			return Mono.defer(() -> {
				if (this.index < filters.size()) {
					GatewayFilter filter = filters.get(this.index);
					DefaultGatewayFilterChain chain = new DefaultGatewayFilterChain(this, this.index + 1);
					return filter.filter(exchange, chain);
				}
				return Mono.empty();
			});
		}
	}
 }
java 复制代码
public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
    private LoadBalancerProperties properties;
    protected final LoadBalancerClient loadBalancer;
    
    @Override
	@SuppressWarnings("Duplicates")
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 获取网关URL和协议
		URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
		String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
        // 非负载均衡调用
		if (url == null || (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
			return chain.filter(exchange);
		}
		// 原始链接处理
		addOriginalRequestUrl(exchange, url);

        // 获取服务实例
		final ServiceInstance instance = choose(exchange);

		if (instance == null) {
			throw NotFoundException.create(properties.isUse404(), ...);
		}

        // 获取URI
		URI uri = exchange.getRequest().getURI();

		// 请求协议
		String overrideScheme = instance.isSecure() ? "https" : "http";
		if (schemePrefix != null) {
			overrideScheme = url.getScheme();
		}

        // 获取请求真实URL
		URI requestUrl = loadBalancer.reconstructURI(
				new DelegatingServiceInstance(instance, overrideScheme), uri);

        // 修改请求路径
		exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
        // 继续处理
		return chain.filter(exchange);
	}
    
    public static void addOriginalRequestUrl(ServerWebExchange exchange, URI url) {
		exchange.getAttributes().computeIfAbsent(GATEWAY_ORIGINAL_REQUEST_URL_ATTR,s -> new LinkedHashSet<>());
		LinkedHashSet<URI> uris = exchange.getRequiredAttribute(GATEWAY_ORIGINAL_REQUEST_URL_ATTR);
		uris.add(url);
	}

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

4.4 结果处理

java 复制代码
public class DispatcherHandler implements WebHandler, ApplicationContextAware {
    private Mono<Void> handleResult(ServerWebExchange exchange, HandlerResult result) {
		return getResultHandler(result).handleResult(exchange, result)
				.onErrorResume( ex -> result.applyExceptionHandler(ex).flatMap(
                        exceptionResult -> getResultHandler(exceptionResult).handleResult(exchange, exceptionResult)
                    )
                );
	}
	private HandlerResultHandler getResultHandler(HandlerResult handlerResult) {
		if (this.resultHandlers != null) {
			for (HandlerResultHandler resultHandler : this.resultHandlers) {
				if (resultHandler.supports(handlerResult)) {
					return resultHandler;
				}
			}
		}
		throw new IllegalStateException(...);
	}
}
相关推荐
追逐时光者4 小时前
推荐 12 款开源美观、简单易用的 WPF UI 控件库,让 WPF 应用界面焕然一新!
后端·.net
Jagger_4 小时前
敏捷开发流程-精简版
前端·后端
苏打水com5 小时前
数据库进阶实战:从性能优化到分布式架构的核心突破
数据库·后端
间彧6 小时前
Spring Cloud Gateway与Kong或Nginx等API网关相比有哪些优劣势?
后端
间彧6 小时前
如何基于Spring Cloud Gateway实现灰度发布的具体配置示例?
后端
间彧6 小时前
在实际项目中如何设计一个高可用的Spring Cloud Gateway集群?
后端
间彧6 小时前
如何为Spring Cloud Gateway配置具体的负载均衡策略?
后端
间彧6 小时前
Spring Cloud Gateway详解与应用实战
后端
EnCi Zheng7 小时前
SpringBoot 配置文件完全指南-从入门到精通
java·spring boot·后端
烙印6018 小时前
Spring容器的心脏:深度解析refresh()方法(上)
java·后端·spring