目录
4.在配置文件中配置Predicate和Gateway Filter的两种方式
RemoteAddrRoutePredicateFactory
AddRequestHeaderGatewayFilterFactory
AddRequestParameterGatewayFilterFactory
AddResponseHeaderGatewayFilterFactory
DedupeResponseHeaderGatewayFilter
RemoteAddrRoutePredicateFactory
AddRequestHeaderGatewayFilterFactory
AddRequestParameterGatewayFilterFactory
AddResponseHeaderGatewayFilterFactory
DedupeResponseHeaderGatewayFilter
前言
基于3.0.2版本的英文文档翻译,加上个人理解进行总结,如若有误,欢迎指正。
持续更新中,觉得有用的点个赞吧....
Gateway是什么
Gateway是一个构建于Spring Boot 2.x, Spring 5(Spring WebFlux), and Project Reactor的Spring生态系统之上的网关,旨在提共一个简单有效的方式路由接口,并提供跨领域的关注点,比如安全,监控,恢复能力。
能够使用网关去进行鉴权,日志记录等。
特征
- 基于springframework5、projectreactor和springboot2.0构建
- 能够匹配任何请求属性上的路由。
- 特定于路由的断言(Predicates )和过滤器(filters )
- 集成熔断
- 集成Spring Cloud DiscoveryClient
- 易于编写断言(Predicates )和过滤器(filters )
- 请求速率限制
- 路径重写
1.如何包含Spring Cloud Gateway
在pom文件中引入如下依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
Spring Cloud Gateway需要SpringBoot和SpringWebFlux提供的Netty作为运行时的容器。它不能在传统的Servlet容器中工作,也不能在构建为war。
2.关键词
Route:网关的基本构建模块,由一个id,一个目标url,一个断言器(Predicates )集合和过滤器(filters)集合组成,如果所有的断言器都是true,则匹配路由。
Predicate: Java8的函数接口。输入类型是 Spring Framework ServerWebExchange
.允许您匹配来自HTTP请求的任何内容,例如请求头或参数
Filter:被特定工厂构建的GatewayFilter实例。在这里,您可以在发送请求之前或之后修改请求和响应。
3.工作原理
原理图
原理
如果客户端向网关发起一个请求,网关处理器正确映射请求到对应的路由,就会把请求发送给网关web拦截器,这个拦截器会使用这个请求对应的过滤器链去执行这个请求。
过滤器被虚线分割的原因是,过滤器可以在代理请求发送之前和之后运行逻辑。执行所有“预”过滤器逻辑。然后发出代理请求。在发出代理请求之后,运行“post”过滤器逻辑。
注意
spring.cloud.gateway.routes[0].uri=http://localhost 端口默认为80
spring.cloud.gateway.routes[0].uri=https://localhost 端口默认为443
如果在没有端口的路由中定义的uri分别为HTTP和HTTPS uri获取默认端口值80和443。
4.在配置文件中配置Predicate和Gateway Filter的两种方式
简写
规则:配置由筛选器名称、等号(=)和用逗号(,)分隔的参数值识别。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
## - Header=Connection,keep-alive
解释:当请求中的cookie包含名称为mycookie=mycookievalue的时候,匹配路由https://example.org
其中Cookie是断言工厂的一种,其他可填写的断言可通过RoutePredicateFactory方式查找可填写的key,例如关于请求头的HeaderRoutePredicateFactory,就可以写为Header=Connection,keep-alive。
完全展开
键值对书写,一般带有name和args两个key.args是用于配置Predicate或Gateway Filter的键值对映射。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
5.Route Predicate Factories
匹配路由的断言工程,可根据各种条件进行路由的匹配。
AfterRoutePredicateFactory
作用:接收一个java ZonedDateTime类(格式为:2021-04-19T16:43:52.634+08:00[Asia/Shanghai])的时间参数。代表,在这个时间之后的请求才能正确匹配路由。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2021-04-19T17:42:47.789-07:00[Asia/Shanghai]
解释:在2021年4月19号17点42分后的请求才能正确路由到https://example.org
BeforeRoutePredicateFactory
作用:接收一个java ZonedDateTime类(格式为:2021-04-19T16:43:52.634+08:00[Asia/Shanghai])的时间参数。代表在这个时间之前的请求才能正确匹配路由。
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Before=2021-04-19T17:42:47.789-07:00[Asia/Shanghai]
解释:在2021年4月19号17点42分之前的请求才能正确路由到https://example.org
BetweenRoutePredicateFactory
作用:接收两个java ZonedDateTime类(格式为:2021-04-19T16:43:52.634+08:00[Asia/Shanghai])的时间参数。代表在第一时间之后,第二个时间之前的请求能被正确路由。
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2021-04-19T00:00:00.000-00:00[America/Denver], 2021-04-20T00:00:00.000-00:00[America/Denver]
解释:在2021-4-19号到2021-4-20号间的请求能被正确路由到https://example.org
CookieRoutePredicateFactory
作用:接收两个参数,分别为name和regexp
(java的正则表达式),cookie中携带参数(name)满足正则表达式(regexp
),则被路由
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
解释:当请求的cookie携带key为chocolate的,值匹配ch.p的表达式(即当chocolate=ch.p),则被路由到https://example.org。
HeaderRoutePredicateFactory
作用:接收两个参数,分别为name和regexp
(java的正则表达式),cookie中携带参数(name)满足正则表达式(regexp
),则被路由
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
解释:当请求头携带key为X-Request-Id的,值包含数字的情况下,则被路由到https://example.org。
HostRoutePredicateFactory
作用:接收一个主机名称表达式集合的参数,该路径表达式支持ant-style风格。也支持模板变量(例如:{sub}.myhost.org)
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
解释:当请求头中有Host参数,且值为www.somehost.org 或者deta.somehost.org或者www.anotherhost.org时,能正确路由https://example.org
主机地址支持接收模板变量(例1.{sub}.somehost.org,当请求地址主机为www.somehost.org时,sub=www,以somehost.org结尾的主机地址都能被路由;
例子2:{sub},当请求地址为www.somehost.org,sub=www.somehost.org,代表来自任何主机的请求都能被路由。
Predicate会提取uri模板变量作为map集合,并放置在ServerWebExchange.getAttributes()中,key为ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE,这些变量值能在GatewayFilter
factories中使用。
MethodRoutePredicateFactory
作用:接收一个或多个http请求方法参数,如果请求方法匹配,则被路由。
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
解释:当http请求为get或post请求时,能正确路由https://example.org
PathRoutePredicateFactory
作用:接收两个参数,路径表达式(Spring PathMatcher
patterns
)集合和一个名为matchTrailingSlash(默认为true)的参数,如果请求路径能够匹配,则被路由
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
解释:当请求路径为/red/1
or /red/1/
or /red/blue
or /blue/green
时,能正确路由https://example.org
如果matchTrailingSlash为false,则 /red/1/不能被路由。
segment为predicate提取的模板变量,可使用工具类轻松获取。
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
QueryRoutePredicateFactory
作用:提供两个参数:必选的param和可选的regexp。如果请求保护一个
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=color
解释:如果请求方法携带一个为color的参数,则路由匹配。例如:http://localhost:8080/getColor?color=green
- Query=color,gree. 如果请求方法携带一个为color的参数,且值为gree开头的,则路由匹配。例如:http://localhost:8080/getColor?color=green,http://localhost:8080/getColor?color=greet
ReadBodyPredicateFactory
备注:这个类为BETA,在未来版本中可能会被改动。
RemoteAddrRoutePredicateFactory
作用:接收一个至少为1个长度的(IPv4或IPv6地址字符串)的远程地址资源集合,例如192.168.0.1/16,192.168.0.1是地址,16是子网前缀范围地址。
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
解释:如果一个请求的远程地址为192.168.1.10,则路由匹配。
备注:默认情况下,RemoteAddrRoutePredicateFactory使用传入请求的的远程地址。如果gateway位于代理层之后,那么可能与实际的客户端ip地址不一致。可以通过设置自定义RemoteAddressResolver,可以自定义解析客户端ip获取方式。
Spring Cloud Gateway提供了一个基于X-Forwarded-For头的非默认远程地址解析器XForwardedRemoteAddressResolver。
XForwardedRemoteAddressResolver提供两个静态方法,采用不同的安全策略
trustAll:返回一个RemoteAddressResolver,它总是取X-Forwarded-For头中的第一个IP地址。它是易受欺骗攻击。因为恶意的客户端能够设置X-Forwarded-For的初始值。程序解析时,就会接受该值。
maxTrustedIndex:采用索引,而且该索引与Spring Cloud Gateway前面受信任的访问点有关。如果反问仅能通过HAProxy代理,那么maxTrustedIndex应该设置为1,如果有两个需要设置为2。
例如:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
maxTrustedIndex值将产生以下远程地址:
maxTrustedIndex | result |
---|---|
[ | (无效, 初始化期间抛出 |
1 | 0.0.0.3 |
2 | 0.0.0.2 |
3 | 0.0.0.1 |
[4, | 0.0.0.1 |
关于X-Forwarded-For的介绍
可以通过以下方式配置:
@Configuration
public class GatewayConfig {
@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
.maxTrustedIndex(1);
return builder.routes()
.route("direct-route",r->r.remoteAddr("10.1.1.1","10.10.1.1/24").uri("https://downstream1"))
.route("proxy-route",r->r.remoteAddr(resolver,"10.10.1.1","10.10.1.1/24").uri("https://downstream2"))
.build();
}
}
WeightRoutePredicateFactory
作用:权重路由断言接收两个参数,group和weight(int类型),每个组(group)根据权重进行计算。
spring:
cloud:
gateway:
routes:
- id: weight_high
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2
解释:当客户端发起请求,80%被路由到https://weighthigh.org,20%被路由https://weightlow.org,可以进行负载均衡。
6.GatewayFilter Factories
路由过滤器运行以特定的方式修改传入的http请求或者传出的http响应,并往下游http传递修改后的信息。官方单元测试地址
过滤器命名方式都是xxxGatewayFilter.配置文件可填写的过滤器名称也都是GatewayFilter之前的名称。
AddRequestHeaderGatewayFilterFactory
作用:接收两个参数name,value。在修改传入的http请求,并往下游请求头添加信息。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: http://localhost:8086
predicates:
- Path=/comsuer-8086/**
filters:
- StripPrefix=1
- AddRequestHeader=X-Request-Red,eee
解释:当访问http://localhost:8087/comsuer-8086/nacos/comsuer?user=zhangsan,时,路径匹配到后,会往请求头中添加X-Request-Red=eee,并路由到http://localhost:8087//nacos/comsuer?user=zhangsan,通过断点可以获取到请求头中X-Request-Red的信息为eee.
AddRequestHeader能够使用匹配path或host的uri变量
例如:
当传入请求http://localhost:8080/red/test时,segment=test,请求头中添加X-Request-Red=Blue-test,并传给下游请求获取。
{segment}相当于一个占位符,如果请求为http://localhost:8080/red/test/haha,则无法路由到https://example.org。
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}
AddRequestParameterGatewayFilterFactory
作用:接收两个变量,name和value。给所有匹配路由规则的请求添加请求参数。
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=color, blue
解释:客户端像网关发起请求,会往匹配的路由https://example.org添加请求参数https://example.org?color=blue
支持uri变量,例如:
http://localhost:8080/red/test请求网关,{segment}=test,请求参数添加foo=bar-test,被路由到https://example.org后变成https://example.orgfoo=bar-test
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestParameter=foo, bar-{segment}
AddResponseHeaderGatewayFilterFactory
作用:接收两个参数name,value。在传出的http响应时,并往响应头添加信息。
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Bl
解释:当http请求返回时,响应头中会添加X-Response-Red=Bl
DedupeResponseHeaderGatewayFilter
作用:接收两个参数name(必填),strategy(可选)。name是一个以空格为分割符的集合。消除响应头中重复的数据。
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
解释:当网关跨域和下游请求都添加了Access-Control-Allow-Credentials和Access-Control-Allow-Origin,将会删除他们的重复值。
CircuitBreakerGatewayFilter
作用:使用Spring Cloud CircuitBreaker 的api将网关路由包装到熔断器中。Spring Cloud CircuitBreaker提供了多个库能够被网关使用。比如 Resilience4J的开箱即用。
想要启用Spring Cloud CircuitBreaker 过滤器的功能,需要引入spring-cloud-starter-circuitbreaker-reactor-resilience4j包,并根据如下配置:
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker
解释:如何配置myCircuitBreaker,可以看Resilience4J Documentation
这个CircuitBreaker过滤器还可添加可选的参数fallbackUri。仅仅支持forward:约束的URIs 。如果失败回调被调用,将会转发到匹配这个uri的controller
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
也可以写成如下配置
Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))
.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}
当请求被熔断,失败回调时,会被转发到网关内部的控制器/inCaseofFailureUseThis。还可以使用重新路由请求到外部的控制器或拦截器的方式进行失败回调。
例如:
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: CircuitBreaker
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
以状态码触发断路器
在某些情况下,希望以路由返回的状态码来进行触发熔断。断路器配置状态码集合,如果返回的状态码保护在集合中,将触发断路器。状态码可以设置数值或字符串
例如:
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
statusCodes:
- 500
- "NOT_FOUND"
使用bean方式配置
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))
.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}
FallbackHeadersGatewayFilter
作用:当请求通过fallbackUri转发到外部应用时,FallbackHeaders允许添加Spring Cloud CircuitBreaker熔断器的异常信息到请求头中,
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: CircuitBreaker
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
filters:
- name: FallbackHeaders
args:
executionExceptionTypeHeaderName: Test-Header
解释:当//ingredients/**的请求触发了熔断,回调了fallbackUri,将请求转发到/fallback,即匹配上ingredients-fallback路由,然后触发FallbackHeaders将异常信息Test-Header添加到请求头中,传给http://localhost:9994/fallback请求。
可以通过重写覆盖请求头的名称,以下展示了默认值:
-
executionExceptionTypeHeaderName
("Execution-Exception-Type"
) -
executionExceptionMessageHeaderName
("Execution-Exception-Message"
) -
rootCauseExceptionTypeHeaderName
("Root-Cause-Exception-Type"
) -
rootCauseExceptionMessageHeaderName
("Root-Cause-Exception-Message"
)
更多关于熔断器和网关的信息可查看Spring Cloud CircuitBreaker Factory section.
MapRequestHeaderGatewayFilter
作用:MapRequestHeader提供两个参数fromHeader,toHeader。会将传入的请求中对应请求头(fromHeader参数对应得请求头名称)得信息,赋值给toHeader请求头,以供下游使用。
spring:
cloud:
gateway:
routes:
- id: map_request_header_route
uri: https://example.org
filters:
- MapRequestHeader=Blue, X-Request-Red
解释:如果传入的http请求头携带Blue名称的值,MapRequestHeader将会根据Blue对应得值更新X-Request-Red,并添加到请求头:X-Request-Red:<values>。如果没有Blue请求头,MapRequestHeader将不会被触发。
PrefixPath
GatewayFilter
作用:提供一个prefix的参数。给传入的请求添加前缀。
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
解释:所有匹配的请求将添加/mypath路径,例如/red请求,将变成/mypath/red.
GatewayFilter其余过滤器
待续。。。。。。。
其余文档链接
2021年Spring Cloud Gateway中文文档详细解析(7-·19章)(3.0.2版)