003-spring cloud gateway-概述、Route模型、网关初始化配置过程、基本原理
一、概述
网关服务核心是将进入的请求正确合理的路由到下层具体的服务进行业务处理,由此可见网关服务的核心就是路由信息的构建。
Spring Cloud Gateway旨在提供一种简单而有效的方式来路由到API,并为他们提供横切关注点,例如:安全性,监控/指标和弹性。
Spring Cloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Netflix Zuul,其不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全、监控、埋点和限流等。
Spring Cloud Gateway 的特征:
- 基于 Spring Framework 5,Project Reactor 和 Spring Boot 2.0
- 动态路由
- Predicates 和 Filters 作用于特定路由
- 集成 Hystrix 断路器
- 集成 Spring Cloud DiscoveryClient
- 易于编写的 Predicates 和 Filters
- 限流
- 路径重写
1.1、Route模型
1、查看具体Route模型类
源码:
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; }
一个Route路由的基本构建块:
- id:路由ID编号,唯一。不写是UUID
- uri:路由导向的目标URI,对应的具体业务服务的URL。http请求为lb://前缀 + 服务id;ws请求为lb:ws://前缀 + 服务id;表示将请求负载到哪一个服务上。当然也可以具体地址
- order:顺序,当请求匹配多个路由时,使用顺序小的
- predicate: 请求匹配路由的断言条件,如果聚合谓词为真,则匹配路由。Java 8 的函数, Spring Framework
ServerWebExchange允许开发人员匹配HTTP请求中的任何内容,例如标头或参数。
- gatewayFilters: 当前路由上存在的过滤器,用于对请求做拦截处理。使用特定工厂构建
org.springframework.cloud.gateway.filter.GatewayFilter
的实例。这里,可以在发送下游请求之前或之后修改请求和响应。
2、Route模型是通过RouteDefinition(路由定义)模型构建的
源码:
@Validated public class RouteDefinition { @NotEmpty private String id = UUID.randomUUID().toString(); @NotEmpty @Valid private List<PredicateDefinition> predicates = new ArrayList(); @Valid private List<FilterDefinition> filters = new ArrayList(); @NotNull private URI uri; private int order = 0; }
其中RouteDefinition代码包含两个数组分别是PredicateDefinition,FilterDefinition。
3、 PredicateDefinition和FilterDefinition
PredicateDefinition : 断言条件(谓语)定义,构建 Route 时,PredicateDefinition 转换成 Predicate
FilterDefinition : 过滤条件的定义,构建Route 时,FilterDefinition 转换成 GatewayFilter
PredicateDefinition源码:
@Validated public class PredicateDefinition { @NotNull private String name; private Map<String, String> args = new LinkedHashMap(); }
- name:名称,Spring-Cloud-Gateway会根据name找到Predicate的构建工厂类
- args:参数,构建Predicate的参数
FilterDefinition源码:
@Validated public class FilterDefinition { @NotNull private String name; private Map<String, String> args = new LinkedHashMap(); }
- name:名称,Spring-Cloud-Gateway会根据name找到GatewayFilter的构建工厂类
- args:参数,构建GatewayFilter的参数
综合上述,Spring-Cloud-Gateway构建路由的数据流向
1.2、网关初始化过程
# Auto Configure org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.cloud.gateway.config.GatewayClassPathWarningAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayLoadBalancerClientAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayMetricsAutoConfiguration,\ org.springframework.cloud.gateway.config.GatewayRedisAutoConfiguration,\ org.springframework.cloud.gateway.discovery.GatewayDiscoveryClientAutoConfiguration
附注:springboot常用的注解的含义
执行顺序
@AutoConfigureAfter:在指定的配置类初始化后再加载
@AutoConfigureBefore:在指定的配置类初始化前加载
@AutoConfigureOrder:数越小越先初始化
条件配置
@ConditionalOnClass : classpath中存在该类时起效
@ConditionalOnMissingClass : classpath中不存在该类时起效
@ConditionalOnBean : DI容器中存在该类型Bean时起效
@ConditionalOnMissingBean : DI容器中不存在该类型Bean时起效
@ConditionalOnSingleCandidate : DI容器中该类型Bean只有一个或@Primary的只有一个时起效
@ConditionalOnExpression : SpEL表达式结果为true时
@ConditionalOnProperty : 参数设置或者值一致时起效
@ConditionalOnResource : 指定的文件存在时起效
@ConditionalOnJndi : 指定的JNDI存在时起效
@ConditionalOnJava : 指定的Java版本存在时起效
@ConditionalOnWebApplication : Web应用环境下起效
@ConditionalOnNotWebApplication : 非Web应用环境下起效
配置文件分析
1、GatewayClassPathWarningAutoConfiguration配置
GatewayClassPathWarningAutoConfiguration配置用于检查项目是否正确导入 spring-boot-starter-webflux 依赖,而不是错误导入 spring-boot-starter-web 依赖,同时 GatewayClassPathWarningAutoConfiguration配置在EnableAutoConfiguration配置加载前加载。
@Configuration //执行顺序注解 //当前注解标识需要在GatewayAutoConfiguration前加载此配置 @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() {} @Configuration //条件判断注解 //classpath中不存在org.springframework.web.reactive.DispatcherHandler时起效,标识项目未导入了spring-boot-starter-webflux包 @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"); } } @Configuration //条件判断注解 //classpath中存在org.springframework.web.servlet.DispatcherServlet时起效,标识项目导入了spring-boot-starter-web包 @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、GatewayLoadBalancerClientAutoConfiguration
@Configuration //条件判断注解 //classpath中存在LoadBalancerClient和RibbonAutoConfiguration和DispatcherHandler时此配置起效 @ConditionalOnClass({LoadBalancerClient.class, RibbonAutoConfiguration.class, DispatcherHandler.class}) //执行顺序注解 @AutoConfigureAfter({RibbonAutoConfiguration.class}) public class GatewayLoadBalancerClientAutoConfiguration { public GatewayLoadBalancerClientAutoConfiguration() { } // GlobalFilter beans @Bean //条件判断注解 //DI容器中存在LoadBalancerClient类型Bean时起效 @ConditionalOnBean({LoadBalancerClient.class}) public LoadBalancerClientFilter loadBalancerClientFilter(LoadBalancerClient client) { return new LoadBalancerClientFilter(client); } }
3、GatewayRedisAutoConfiguration
GatewayRedisAutoConfiguration 配置作用是初始化初始化 RedisRateLimiter 限流功能的RequestRateLimiterGatewayFilterFactory 基于 RedisRateLimiter 实现网关的限流功能。4、GatewayAutoConfiguration
GatewayAutoConfiguration配置是Spring Cloud Gateway 核心配置类,初始化如下 :
- NettyConfiguration 底层通信netty配置
- GlobalFilter (AdaptCachedBodyGlobalFilter,RouteToRequestUrlFilter,ForwardRoutingFilter,ForwardPathFilter,WebsocketRoutingFilter,WeightCalculatorWebFilter等)
- FilteringWebHandler
- GatewayProperties
- PrefixPathGatewayFilterFactory
- RoutePredicateFactory
- RouteDefinitionLocator
- RouteLocator
- RoutePredicateHandlerMapping 查找匹配到 Route并进行处理
- GatewayWebfluxEndpoint 管理网关的 HTTP API
// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.cloud.gateway.config; import com.netflix.hystrix.HystrixObservableCommand; import io.netty.channel.ChannelOption; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import java.security.cert.X509Certificate; import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.actuate.autoconfigure.endpoint.condition.ConditionalOnEnabledEndpoint; import org.springframework.boot.actuate.health.Health; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.web.reactive.HttpHandlerAutoConfiguration; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.PropertyMapper; import org.springframework.cloud.gateway.actuate.GatewayControllerEndpoint; import org.springframework.cloud.gateway.config.HttpClientProperties.Pool; import org.springframework.cloud.gateway.config.HttpClientProperties.Proxy; import org.springframework.cloud.gateway.config.HttpClientProperties.Ssl; import org.springframework.cloud.gateway.config.HttpClientProperties.Pool.PoolType; import org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter; import org.springframework.cloud.gateway.filter.ForwardPathFilter; import org.springframework.cloud.gateway.filter.ForwardRoutingFilter; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.cloud.gateway.filter.NettyRoutingFilter; import org.springframework.cloud.gateway.filter.NettyWriteResponseFilter; import org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter; import org.springframework.cloud.gateway.filter.WebsocketRoutingFilter; import org.springframework.cloud.gateway.filter.WeightCalculatorWebFilter; import org.springframework.cloud.gateway.filter.factory.AddRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.AddRequestParameterGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.AddResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.GatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.HystrixGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.PrefixPathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RedirectToGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RemoveRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RemoveResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestHeaderToRequestUriGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RequestRateLimiterGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RetryGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SaveSessionGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SecureHeadersGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SecureHeadersProperties; import org.springframework.cloud.gateway.filter.factory.SetPathGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetRequestHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetResponseHeaderGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.SetStatusGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.StripPrefixGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyRequestBodyGatewayFilterFactory; import org.springframework.cloud.gateway.filter.factory.rewrite.ModifyResponseBodyGatewayFilterFactory; import org.springframework.cloud.gateway.filter.headers.ForwardedHeadersFilter; import org.springframework.cloud.gateway.filter.headers.HttpHeadersFilter; import org.springframework.cloud.gateway.filter.headers.RemoveHopByHopHeadersFilter; import org.springframework.cloud.gateway.filter.headers.XForwardedHeadersFilter; import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver; import org.springframework.cloud.gateway.filter.ratelimit.PrincipalNameKeyResolver; import org.springframework.cloud.gateway.filter.ratelimit.RateLimiter; import org.springframework.cloud.gateway.handler.FilteringWebHandler; import org.springframework.cloud.gateway.handler.RoutePredicateHandlerMapping; import org.springframework.cloud.gateway.handler.predicate.AfterRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.BeforeRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.BetweenRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.CloudFoundryRouteServiceRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.CookieRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.HeaderRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.HostRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.MethodRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.QueryRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.ReadBodyPredicateFactory; import org.springframework.cloud.gateway.handler.predicate.RemoteAddrRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.RoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.WeightRoutePredicateFactory; import org.springframework.cloud.gateway.route.CachingRouteLocator; import org.springframework.cloud.gateway.route.CompositeRouteDefinitionLocator; import org.springframework.cloud.gateway.route.CompositeRouteLocator; import org.springframework.cloud.gateway.route.InMemoryRouteDefinitionRepository; import org.springframework.cloud.gateway.route.RouteDefinitionLocator; import org.springframework.cloud.gateway.route.RouteDefinitionRepository; import org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator; import org.springframework.cloud.gateway.route.RouteDefinitionWriter; import org.springframework.cloud.gateway.route.RouteLocator; import org.springframework.cloud.gateway.route.RouteRefreshListener; import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.Primary; import org.springframework.http.codec.ServerCodecConfigurer; import org.springframework.util.StringUtils; import org.springframework.validation.Validator; import org.springframework.web.reactive.DispatcherHandler; import org.springframework.web.reactive.socket.client.ReactorNettyWebSocketClient; import org.springframework.web.reactive.socket.client.WebSocketClient; import org.springframework.web.reactive.socket.server.WebSocketService; import org.springframework.web.reactive.socket.server.support.HandshakeWebSocketService; import reactor.core.publisher.Flux; import reactor.ipc.netty.http.client.HttpClient; import reactor.ipc.netty.http.client.HttpClientOptions.Builder; import reactor.ipc.netty.resources.PoolResources; import rx.RxReactiveStreams; @Configuration @ConditionalOnProperty( name = {"spring.cloud.gateway.enabled"}, matchIfMissing = true ) @EnableConfigurationProperties @AutoConfigureBefore({HttpHandlerAutoConfiguration.class}) @AutoConfigureAfter({GatewayLoadBalancerClientAutoConfiguration.class, GatewayClassPathWarningAutoConfiguration.class}) @ConditionalOnClass({DispatcherHandler.class}) public class GatewayAutoConfiguration { public GatewayAutoConfiguration() { } @Bean public RouteLocatorBuilder routeLocatorBuilder(ConfigurableApplicationContext context) { return new RouteLocatorBuilder(context); } @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)); } @Bean public RouteLocator routeDefinitionRouteLocator(GatewayProperties properties, List<GatewayFilterFactory> GatewayFilters, List<RoutePredicateFactory> predicates, RouteDefinitionLocator routeDefinitionLocator) { return new RouteDefinitionRouteLocator(routeDefinitionLocator, predicates, GatewayFilters, properties); } @Bean @Primary public RouteLocator cachedCompositeRouteLocator(List<RouteLocator> routeLocators) { return new CachingRouteLocator(new CompositeRouteLocator(Flux.fromIterable(routeLocators))); } @Bean public RouteRefreshListener routeRefreshListener(ApplicationEventPublisher publisher) { return new RouteRefreshListener(publisher); } @Bean public FilteringWebHandler filteringWebHandler(List<GlobalFilter> globalFilters) { return new FilteringWebHandler(globalFilters); } @Bean public GlobalCorsProperties globalCorsProperties() { return new GlobalCorsProperties(); } @Bean public RoutePredicateHandlerMapping routePredicateHandlerMapping(FilteringWebHandler webHandler, RouteLocator routeLocator, GlobalCorsProperties globalCorsProperties) { return new RoutePredicateHandlerMapping(webHandler, routeLocator, globalCorsProperties); } @Bean public GatewayProperties gatewayProperties() { return new GatewayProperties(); } @Bean public SecureHeadersProperties secureHeadersProperties() { return new SecureHeadersProperties(); } @Bean @ConditionalOnProperty( name = {"spring.cloud.gateway.forwarded.enabled"}, matchIfMissing = true ) public ForwardedHeadersFilter forwardedHeadersFilter() { return new ForwardedHeadersFilter(); } @Bean public RemoveHopByHopHeadersFilter removeHopByHopHeadersFilter() { return new RemoveHopByHopHeadersFilter(); } @Bean @ConditionalOnProperty( name = {"spring.cloud.gateway.x-forwarded.enabled"}, matchIfMissing = true ) public XForwardedHeadersFilter xForwardedHeadersFilter() { return new XForwardedHeadersFilter(); } @Bean public AdaptCachedBodyGlobalFilter adaptCachedBodyGlobalFilter() { return new AdaptCachedBodyGlobalFilter(); } @Bean public RouteToRequestUrlFilter routeToRequestUrlFilter() { return new RouteToRequestUrlFilter(); } @Bean @ConditionalOnBean({DispatcherHandler.class}) public ForwardRoutingFilter forwardRoutingFilter(DispatcherHandler dispatcherHandler) { return new ForwardRoutingFilter(dispatcherHandler); } @Bean public ForwardPathFilter forwardPathFilter() { return new ForwardPathFilter(); } @Bean public WebSocketService webSocketService() { return new HandshakeWebSocketService(); } @Bean public WebsocketRoutingFilter websocketRoutingFilter(WebSocketClient webSocketClient, WebSocketService webSocketService, ObjectProvider<List<HttpHeadersFilter>> headersFilters) { return new WebsocketRoutingFilter(webSocketClient, webSocketService, headersFilters); } @Bean public WeightCalculatorWebFilter weightCalculatorWebFilter(Validator validator) { return new WeightCalculatorWebFilter(validator); } @Bean public AfterRoutePredicateFactory afterRoutePredicateFactory() { return new AfterRoutePredicateFactory(); } @Bean public BeforeRoutePredicateFactory beforeRoutePredicateFactory() { return new BeforeRoutePredicateFactory(); } @Bean public BetweenRoutePredicateFactory betweenRoutePredicateFactory() { return new BetweenRoutePredicateFactory(); } @Bean public CookieRoutePredicateFactory cookieRoutePredicateFactory() { return new CookieRoutePredicateFactory(); } @Bean public HeaderRoutePredicateFactory headerRoutePredicateFactory() { return new HeaderRoutePredicateFactory(); } @Bean public HostRoutePredicateFactory hostRoutePredicateFactory() { return new HostRoutePredicateFactory(); } @Bean public MethodRoutePredicateFactory methodRoutePredicateFactory() { return new MethodRoutePredicateFactory(); } @Bean public PathRoutePredicateFactory pathRoutePredicateFactory() { return new PathRoutePredicateFactory(); } @Bean public QueryRoutePredicateFactory queryRoutePredicateFactory() { return new QueryRoutePredicateFactory(); } @Bean public ReadBodyPredicateFactory readBodyPredicateFactory(ServerCodecConfigurer codecConfigurer) { return new ReadBodyPredicateFactory(codecConfigurer); } @Bean public RemoteAddrRoutePredicateFactory remoteAddrRoutePredicateFactory() { return new RemoteAddrRoutePredicateFactory(); } @Bean @DependsOn({"weightCalculatorWebFilter"}) public WeightRoutePredicateFactory weightRoutePredicateFactory() { return new WeightRoutePredicateFactory(); } @Bean public CloudFoundryRouteServiceRoutePredicateFactory cloudFoundryRouteServiceRoutePredicateFactory() { return new CloudFoundryRouteServiceRoutePredicateFactory(); } @Bean public AddRequestHeaderGatewayFilterFactory addRequestHeaderGatewayFilterFactory() { return new AddRequestHeaderGatewayFilterFactory(); } @Bean public AddRequestParameterGatewayFilterFactory addRequestParameterGatewayFilterFactory() { return new AddRequestParameterGatewayFilterFactory(); } @Bean public AddResponseHeaderGatewayFilterFactory addResponseHeaderGatewayFilterFactory() { return new AddResponseHeaderGatewayFilterFactory(); } @Bean public ModifyRequestBodyGatewayFilterFactory modifyRequestBodyGatewayFilterFactory(ServerCodecConfigurer codecConfigurer) { return new ModifyRequestBodyGatewayFilterFactory(codecConfigurer); } @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 RemoveResponseHeaderGatewayFilterFactory removeResponseHeaderGatewayFilterFactory() { return new RemoveResponseHeaderGatewayFilterFactory(); } @Bean( name = {"principalNameKeyResolver"} ) @ConditionalOnBean({RateLimiter.class}) public PrincipalNameKeyResolver principalNameKeyResolver() { return new PrincipalNameKeyResolver(); } @Bean @ConditionalOnBean({RateLimiter.class, KeyResolver.class}) public RequestRateLimiterGatewayFilterFactory requestRateLimiterGatewayFilterFactory(RateLimiter rateLimiter, PrincipalNameKeyResolver resolver) { return new RequestRateLimiterGatewayFilterFactory(rateLimiter, resolver); } @Bean public RewritePathGatewayFilterFactory rewritePathGatewayFilterFactory() { return new RewritePathGatewayFilterFactory(); } @Bean public RetryGatewayFilterFactory retryGatewayFilterFactory() { return new RetryGatewayFilterFactory(); } @Bean public SetPathGatewayFilterFactory setPathGatewayFilterFactory() { return new SetPathGatewayFilterFactory(); } @Bean public SecureHeadersGatewayFilterFactory secureHeadersGatewayFilterFactory(SecureHeadersProperties properties) { return new SecureHeadersGatewayFilterFactory(properties); } @Bean public SetRequestHeaderGatewayFilterFactory setRequestHeaderGatewayFilterFactory() { return new SetRequestHeaderGatewayFilterFactory(); } @Bean public SetResponseHeaderGatewayFilterFactory setResponseHeaderGatewayFilterFactory() { return new SetResponseHeaderGatewayFilterFactory(); } @Bean public SetStatusGatewayFilterFactory setStatusGatewayFilterFactory() { return new SetStatusGatewayFilterFactory(); } @Bean public SaveSessionGatewayFilterFactory saveSessionGatewayFilterFactory() { return new SaveSessionGatewayFilterFactory(); } @Bean public StripPrefixGatewayFilterFactory stripPrefixGatewayFilterFactory() { return new StripPrefixGatewayFilterFactory(); } @Bean public RequestHeaderToRequestUriGatewayFilterFactory requestHeaderToRequestUriGatewayFilterFactory() { return new RequestHeaderToRequestUriGatewayFilterFactory(); } @Configuration @ConditionalOnClass({Health.class}) protected static class GatewayActuatorConfiguration { protected GatewayActuatorConfiguration() { } @Bean @ConditionalOnEnabledEndpoint public GatewayControllerEndpoint gatewayControllerEndpoint(RouteDefinitionLocator routeDefinitionLocator, List<GlobalFilter> globalFilters, List<GatewayFilterFactory> GatewayFilters, RouteDefinitionWriter routeDefinitionWriter, RouteLocator routeLocator) { return new GatewayControllerEndpoint(routeDefinitionLocator, globalFilters, GatewayFilters, routeDefinitionWriter, routeLocator); } } @Configuration @ConditionalOnClass({HystrixObservableCommand.class, RxReactiveStreams.class}) protected static class HystrixConfiguration { protected HystrixConfiguration() { } @Bean public HystrixGatewayFilterFactory hystrixGatewayFilterFactory(DispatcherHandler dispatcherHandler) { return new HystrixGatewayFilterFactory(dispatcherHandler); } } @Configuration @ConditionalOnClass({HttpClient.class}) protected static class NettyConfiguration { protected NettyConfiguration() { } @Bean @ConditionalOnMissingBean public HttpClient httpClient(@Qualifier("nettyClientOptions") Consumer<? super Builder> options) { return HttpClient.create(options); } @Bean public Consumer<? super Builder> nettyClientOptions(HttpClientProperties properties) { return (opts) -> { if (properties.getConnectTimeout() != null) { opts.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, properties.getConnectTimeout()); } Ssl ssl = properties.getSsl(); X509Certificate[] trustedX509Certificates = ssl.getTrustedX509CertificatesForTrustManager(); if (trustedX509Certificates.length > 0) { opts.sslSupport((sslContextBuilder) -> { sslContextBuilder.trustManager(trustedX509Certificates); }); } else if (ssl.isUseInsecureTrustManager()) { opts.sslSupport((sslContextBuilder) -> { sslContextBuilder.trustManager(InsecureTrustManagerFactory.INSTANCE); }); } Pool pool = properties.getPool(); if (pool.getType() == PoolType.DISABLED) { opts.disablePool(); } else { PoolResources poolResources; if (pool.getType() == PoolType.FIXED) { poolResources = PoolResources.fixed(pool.getName(), pool.getMaxConnections(), pool.getAcquireTimeout()); opts.poolResources(poolResources); } else { poolResources = PoolResources.elastic(pool.getName()); opts.poolResources(poolResources); } } Proxy proxy = properties.getProxy(); if (StringUtils.hasText(proxy.getHost())) { opts.proxy((typeSpec) -> { reactor.ipc.netty.options.ClientProxyOptions.Builder builder = typeSpec.type(reactor.ipc.netty.options.ClientProxyOptions.Proxy.HTTP).host(proxy.getHost()); PropertyMapper map = PropertyMapper.get(); proxy.getClass(); map.from(proxy::getPort).whenNonNull().to(builder::port); proxy.getClass(); map.from(proxy::getUsername).whenHasText().to(builder::username); proxy.getClass(); map.from(proxy::getPassword).whenHasText().to((password) -> { builder.password((s) -> { return password; }); }); proxy.getClass(); map.from(proxy::getNonProxyHostsPattern).whenHasText().to(builder::nonProxyHosts); return builder; }); } }; } @Bean public HttpClientProperties httpClientProperties() { return new HttpClientProperties(); } @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(@Qualifier("nettyClientOptions") Consumer<? super Builder> options) { return new ReactorNettyWebSocketClient(options); } } }
5、GatewayDiscoveryClientAutoConfiguration
GatewayDiscoveryClientAutoConfiguration配置的作用是初始化配置路由中的注册发现服务信息// // Source code recreated from a .class file by IntelliJ IDEA // (powered by Fernflower decompiler) // package org.springframework.cloud.gateway.discovery; import java.util.ArrayList; import java.util.List; import org.springframework.boot.autoconfigure.AutoConfigureAfter; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.client.discovery.composite.CompositeDiscoveryClientAutoConfiguration; import org.springframework.cloud.gateway.config.GatewayAutoConfiguration; import org.springframework.cloud.gateway.filter.FilterDefinition; import org.springframework.cloud.gateway.filter.factory.RewritePathGatewayFilterFactory; import org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory; import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition; import org.springframework.cloud.gateway.support.NameUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.reactive.DispatcherHandler; @Configuration @ConditionalOnProperty( name = {"spring.cloud.gateway.enabled"}, matchIfMissing = true ) @AutoConfigureBefore({GatewayAutoConfiguration.class}) @AutoConfigureAfter({CompositeDiscoveryClientAutoConfiguration.class}) @ConditionalOnClass({DispatcherHandler.class, DiscoveryClient.class}) @EnableConfigurationProperties public class GatewayDiscoveryClientAutoConfiguration { public GatewayDiscoveryClientAutoConfiguration() { } @Bean @ConditionalOnBean({DiscoveryClient.class}) @ConditionalOnProperty( name = {"spring.cloud.gateway.discovery.locator.enabled"} ) public DiscoveryClientRouteDefinitionLocator discoveryClientRouteDefinitionLocator(DiscoveryClient discoveryClient, DiscoveryLocatorProperties properties) { return new DiscoveryClientRouteDefinitionLocator(discoveryClient, properties); } @Bean public DiscoveryLocatorProperties discoveryLocatorProperties() { DiscoveryLocatorProperties properties = new DiscoveryLocatorProperties(); properties.setPredicates(initPredicates()); properties.setFilters(initFilters()); return properties; } public static List<PredicateDefinition> initPredicates() { ArrayList<PredicateDefinition> definitions = new ArrayList(); PredicateDefinition predicate = new PredicateDefinition(); predicate.setName(NameUtils.normalizeRoutePredicateName(PathRoutePredicateFactory.class)); predicate.addArg("pattern", "'/'+serviceId+'/**'"); definitions.add(predicate); return definitions; } public static List<FilterDefinition> initFilters() { ArrayList<FilterDefinition> definitions = new ArrayList(); FilterDefinition filter = new FilterDefinition(); filter.setName(NameUtils.normalizeFilterFactoryName(RewritePathGatewayFilterFactory.class)); String regex = "'/' + serviceId + '/(?<remaining>.*)'"; String replacement = "'/${remaining}'"; filter.addArg("regexp", regex); filter.addArg("replacement", replacement); definitions.add(filter); return definitions; } }
二、使用
2.1、pom引用
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
关闭:spring.cloud.gateway.enabled=false
注意:Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty运行时。它不能在传统的Servlet容器中工作或构建为WAR。