一、概述
网关服务核心是将进入的请求正确合理的路由到下层具体的服务进行业务处理,由此可见网关服务的核心就是路由信息的构建。
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。