docs/Spring全家桶/SpringCloud源码分析/SpringCloudGateway源码分析.md
ѧϰĿ
1. GatewayClassPathWarningAutoConfiguration
@Configuration(proxyBeanMethods = false)
//ǰGatewayAutoConfiguration֮ǰ
@AutoConfigureBefore(GatewayAutoConfiguration.class)
public class GatewayClassPathWarningAutoConfiguration {
...
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "org.springframework.web.servlet.DispatcherServlet")
protected static class SpringMvcFoundOnClasspathConfiguration {
public SpringMvcFoundOnClasspathConfiguration() {
log.warn(BORDER
+ "Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway at this time. "
+ "Please remove spring-boot-starter-web dependency." + BORDER);
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("org.springframework.web.reactive.DispatcherHandler")
protected static class WebfluxMissingFromClasspathConfiguration {
public WebfluxMissingFromClasspathConfiguration() {
log.warn(BORDER + "Spring Webflux is missing from the classpath, "
+ "which is required for Spring Cloud Gateway at this time. "
+ "Please add spring-boot-starter-webflux dependency." + BORDER);
}
}
}
ܿʵϾͨConditionOnClassConditionOnMissingClass־ӡĹܣClassPath org.springframework.web.servlet.DispatcherServletĻʵһBeanȻӡ־spring-boot-starter-webȻټClassPathǷȷwebfluxûУӡ־spring-boot-starter-webflux
2.GatewayAutoConfiguration
Ϊ̫ͲչʾˣоټȽҪ
3.HttpHandlerAutoConfigurationWebFluxAutoConfiguration࣬GatewayAutoConfiguration֮ʵֱʵHttpHandlerWebFluxConfigBean
2 ִ һнHystrixԭHystrixкҵͨӦʽɵģʵϣGatewayҲǻͬı̷ͬģGatewayͬSpringMVCҲdzơ
ǰʱ£
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
if (this.handlerMappings == null) {
return createNotFoundError();
}
//webFluxӦʽ
return Flux
// 1.DZе handlerMapping
.fromIterable(this.handlerMappings)
// 2.ȡӦhandlerMapping 糣õ RequestMappingHandlerMappingRoutePredicateHandlerMapping
.concatMap(mapping -> mapping.getHandler(exchange))
.next()
.switchIfEmpty(createNotFoundError())
// 3.ȡӦöӦĴ
.flatMap(handler -> invokeHandler(exchange, handler))
// 4.ش
.flatMap(result -> handleResult(exchange, result));
}
2.1 getHandler getHandlerGatewayĺڣgetHandlerлȡӦHandlerMapping
AbstractHandlerMapping.getHandlerԴ
@Override
public Mono<Object> getHandler(ServerWebExchange exchange) {
//һȡ·ɵʵ࣬뵽RoutePredicateHandlerMapping
return getHandlerInternal(exchange).map(handler -> {
if (logger.isDebugEnabled()) {
logger.debug(exchange.getLogPrefix() + "Mapped to " + handler);
}
ServerHttpRequest request = exchange.getRequest();
if (hasCorsConfigurationSource(handler) || CorsUtils.isPreFlightRequest(request)) {
CorsConfiguration config = (this.corsConfigurationSource != null ? this.corsConfigurationSource.getCorsConfiguration(exchange) : null);
CorsConfiguration handlerConfig = 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;
});
}
@Override
protected Mono<?> getHandlerInternal(ServerWebExchange exchange) {
// don't handle requests on management port if set and different than server port
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)
// .log("route-predicate-handler-mapping", Level.FINER) //name this
.flatMap((Function<Route, Mono<?>>) r -> {
//Ƴоɵ
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isDebugEnabled()) {
logger.debug(
"Mapping [" + getExchangeDesc(exchange) + "] to " + r);
}
//Ѹ·İؾ
exchange.getAttributes().put(GATEWAY_ROUTE_ATTR, r);
// webHandler
return Mono.just(webHandler);
}).switchIfEmpty(Mono.empty().then(Mono.fromRunnable(() -> {
exchange.getAttributes().remove(GATEWAY_PREDICATE_ROUTE_ATTR);
if (logger.isTraceEnabled()) {
logger.trace("No RouteDefinition found for ["
+ getExchangeDesc(exchange) + "]");
}
})));
}
lookupRouteҵymlõе·ɶԹBeforeAfterPathȵȣִapply·ƥ䣬жǷִͨ˳springbootԶʱԼƶ
protected Mono<Route> lookupRoute(ServerWebExchange exchange) {
// getRoutes ȡеĶԹ
return this.routeLocator.getRoutes()
.concatMap(route -> Mono.just(route).filterWhen(r -> {
exchange.getAttributes().put(GATEWAY_PREDICATE_ROUTE_ATTR, r.getId());
// ȻȡRouteڲpredicate
//Ȼapply ִжԣжǷͨ
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;
});
}
getRoutes()ͨ RouteDefinitionRouteLocatorļлȡ·ɵģȻҵ·תRoute
@Override
public Flux<Route> getRoutes() {
// getRouteDefinitions() ļлȡ·
Flux<Route> routes = this.routeDefinitionLocator.getRouteDefinitions()
// convertToRoute()ҵ·תRoute
.map(this::convertToRoute);
...
}
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;
...
}
2.2 invokeHandler Gatewayһƥ·ɺصwebHandler͵ģҲҪҵӦHandlerAdaptorȡӦ invokeHandler(exchange, handler)
private Mono<HandlerResult> invokeHandler(ServerWebExchange exchange, Object handler) {
if (this.handlerAdapters != null) {
//ҵеHandlerAdapterȥƥWebFlux
for (HandlerAdapter handlerAdapter : this.handlerAdapters) {
if (handlerAdapter.supports(handler)) {
return handlerAdapter.handle(exchange, handler);
}
}
}
return Mono.error(new IllegalStateException("No HandlerAdapter: " + handler));
}
SimpleHandlerAdapter еhandle
@Override
public Mono<HandlerResult> handle(ServerWebExchange exchange, Object handler) {
//WebHandler
WebHandler webHandler = (WebHandler) handler;
Mono<Void> mono = webHandler.handle(exchange);
return mono.then(Mono.empty());
}
webHandler.handleǴйķùglobalFiltersgatewayFilters
@Override
public Mono<Void> handle(ServerWebExchange exchange) {
// 1\. ·İϵȡӦ·Route
Route route = exchange.getRequiredAttribute(GATEWAY_ROUTE_ATTR);
List<GatewayFilter> gatewayFilters = route.getFilters();
// 2\. ռе globalFilters List<GatewayFilter>
//עʹģʽ
List<GatewayFilter> combined = new ArrayList<>(this.globalFilters);
// 3\. gatewayFilters ҲList<GatewayFilter>γһ
combined.addAll(gatewayFilters);
// 4\. order
AnnotationAwareOrderComparator.sort(combined);
if (logger.isDebugEnabled()) {
logger.debug("Sorted gatewayFilterFactories: " + combined);
}
// 5\. ִйеÿһ
return new DefaultGatewayFilterChain(combined).filter(exchange);
}
ע⣺װʱǰglobalFiltersgatewayFiltersֹŽList<GatewayFilter>Уôأ
ʵõһ ģʽ
Զ http://localhost:9527/get/3Ϊ9527ΪGatewayĶ˿
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 1\. ·İϵ
// ȡԭʼurlhttp://localhost:9527/get/3
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);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url before: " + url);
}
// 2\. ͨribbonĸؾ㷨ݷȥnacosEurekaѡһʵ
// ʵuser url ַhttp://localhost:8080/get/3
final ServiceInstance instance = choose(exchange);
if (instance == null) {
throw NotFoundException.create(properties.isUse404(),
"Unable to find instance for " + url.getHost());
}
// 3\. õԭ uri http://localhost:9527/get/3
URI uri = exchange.getRequest().getURI();
String overrideScheme = instance.isSecure() ? "https" : "http";
if (schemePrefix != null) {
overrideScheme = url.getScheme();
}
// 4\. ÷ʵinstanceuri滻ԭuriַ õ µurl
// µurl: http://localhost:8080/get/3
URI requestUrl = loadBalancer.reconstructURI(
new DelegatingServiceInstance(instance, overrideScheme), uri);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
}
// 5\. ٴμ¼Ĺϵ
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
// 6\. ִйе
return chain.filter(exchange);
}
https://lijunyi.xyz/docs/SpringCloud/SpringCloud.html#_2-2-x-%E5%88%86%E6%94%AF https://mp.weixin.qq.com/s/2jeovmj77O9Ux96v3A0NtA https://juejin.cn/post/6931922457741770760 https://github.com/D2C-Cai/herring http://c.biancheng.net/springcloud https://github.com/macrozheng/springcloud-learning