1. 使用 Spring Cloud Gateway
Srping Cloud Gateway需要Spring Boot和Spring Webflux提供的运行环境。不能运行在传统的Servlet容器或者做为war包构建。
在项目中使用Spring Cloud Gateway,请使用带有group为org.springframework.cloud和artifact为spring-cloud-starter-gateway的starter依赖。
有关使用当前的Spring Cloud发布系列设置构建系统的详细信息,请参阅Spring Cloud Project page。
如果你包含了这个starter依赖,但是,由于某种原因,你不希望gateway被启用,设置s
pring.cloud.gateway.enabled=false
。
2. 术语
Route(路由): 路由是网关的基本组件。它的定义是一个ID,一个目标URI,一组谓词和一组过滤器。如果聚合谓词为真,则匹配路由。
Predicate(谓词): 这是一个 Java 8 Function Predicate.。输入类型是一个 Spring Framework ServerWebExchange.。这允许开发人员对HTTP请求中的任何内容进行匹配,例如头和参数。
Filter(过滤器): 这些都是通过特定工程构建的Spring Framework GatewayFilter 的实例。在这里,可以在发送下游请求之前或之后修改请求和响应。
3. Spring Cloud Gateway的工作流程
客户端向网关发送请求。如果网关处理映射的程序确定请求与路由匹配,它将被发送到网关Web处理程序。此处理程序通过特定于请求的过滤器链发送请求。
过滤器被虚线分隔的原因是过滤器可以在代理请求发送之前或之后执行逻辑。执行所有“pre”过滤逻辑,然后发出代理请求。在发出代理请求之后,将执行“post”过滤器逻辑。
4. 路由谓词工厂
Spring Cloud Gateway将路由匹配为Spring WebFlux HandlerMapping基础设施的一部分。Spring Cloud Gateway包括许多内置路由谓词工厂。
所有的谓词匹配HTTP请求的不同属性。可以组合多个路由谓词工厂,并通过逻辑进行组合。
4.1 After Route Predicate Factory
After Route Predicate Factory接收一个日期时间参数。这个谓词匹配当前日期时间之后发生的请求。
译者:id起一个标识的作用,并不是必须的,如果没有id属性,spring会生成一个uuid的id。
@NotEmpty
private String id = UUID.randomUUID().toString();
application.yml.
spring:
cloud:
gateway:
routes:
- id: after_route
uri: http://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
这个路由匹配了时区为[America/Denver],2017年1月20号17:42:47之后的请求。如果当前请求的时间匹配,则会跳转到uri的地址。
4.2 Before Route Predicate Factory
Before Route Predicate Factory接收一个日期时间参数。这个谓词匹配当前日期时间之前发生的请求。
application.yml.
spring:
cloud:
gateway:
routes:
- id: before_route
uri: http://example.org
predicates:
- Before=2019-01-20T17:42:47.789-07:00[America/Denver]
这个路由匹配了时区为[America/Denver],2019年1月20号17:42:47之前的请求。如果当前请求的时间匹配,则会跳转到uri的地址。
4.3 Between Route Predicate Factory
Between Route Predicate Factory接收2个参数,datetime1和datetime2。这个谓词匹配datetime1之后和datetime2之前发生的请求。datetime2参数必须在datetime1之后。
application.yml.
spring:
cloud:
gateway:
routes:
- id: between_route
uri: http://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2019-01-21T17:42:47.789-07:00[America/Denver]
这个路由匹配了时区为[America/Denver],2017年1月20号17:42:47之后,2019年1月20号17:42:47之前的所有请求。这对维护windows很有用。
4.4 Cookie Route Predicate Factory
Cookie Route Predicate Factory 接收2个参数, cookie名称和一个正则表达式。这个谓词匹配具有给定名称的cookie,而值匹配正则表达式。
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: http://example.org
predicates:
- Cookie=chocolate, ch.p
这个路由匹配包含cookie名为chocolate,其值与ch.p正则表达式匹配的请求。
4.5 Header Route Predicate Factory
Header Route Predicate Factory接收2个参数,一个header中的名称和一个正则表达式。这个谓词与具有给定名称的header,而值匹配正则表达式。
application.yml.
spring:
cloud:
gateway:
routes:
- id: header_route
uri: http://example.org
predicates:
- Header=X-Request-Id, \d+
如果请求有一个名为X-Request-Id的header,其值与\d+正则表达式(值为一个或多个数字)匹配,则此路由将匹配。
4.6 Host Route Predicate Factory
Host Route Predicate Factory接收一个参数,主机名称的模板。这个模板是一个ant分隔的模板,用.号作为分隔符。此谓词匹配主机头的模板。
application.yml.
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Host=**.somehost.org
如果请求有一个主机头,其值为www.somehost.org或beta.somehost.org,则此路由将匹配。
4.7 Method Route Predicate Factory
Method Route Predicate Factory接收一个参数,HTTP请求的方法。
application.yml.
spring:
cloud:
gateway:
routes:
- id: method_route
uri: http://example.org
predicates:
- Method=GET
如果是一个GET请求,这个路由将被匹配。
4.8 Path Route Predicate Factory
Path Route Predicate Factory接收一个参数,一个Spring PathMatcher
模板。
application.yml.
spring:
cloud:
gateway:
routes:
- id: host_route
uri: http://example.org
predicates:
- Path=/foo/{segment}
如果请求路径符合要求,则此路由将匹配,例如:/foo/1
或者 /foo/bar
。
该谓词提取URI模板变量作为名称和值的映射(就像上面例子中定义的segment),并将其放入ServerWebExchange.getAttributes()中,并在PathRoutePredicate.URL_PREDICATE_VARS_ATTR
中定义一个key。
然后,这些知可以供GatewayFilter Factories使用。
4.9 Query Route Predicate Factory
Query Route Predicate Factory 接收2个参数: 一个必须的参数和一个可选的表达式
。
application.yml.
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=baz
如果请求包含baz查询参数,则此路由将匹配。
application.yml.
spring:
cloud:
gateway:
routes:
- id: query_route
uri: http://example.org
predicates:
- Query=foo, ba.
如果请求包含一个foo查询参数,其值与ba.匹配,则其路由将匹配。例如foo=bar和foo=baz。
4.10 RemoteAddr Route Predicate Factory
RemoteAddr Route Predicate Factory接受cidr符号(IPv4或IPv6)字符串的列表(最小大小为1),例如192.168.0.1/16(其中192.168.0.1是IP地址,16是子网掩码)。
application.yml.
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: http://example.org
predicates:
- RemoteAddr=192.168.1.1/24
如果请求的远程地址是192.168.1.10,则此路由将匹配。
4.10.1 修改远程地址解析的方式
默认情况下,RemoteAddr Route Predicate Factory使用来自传入请求的远程地址。如果Spring Cloud网关位于代理层后面,这可能与实际客户端IP地址不匹配。
您可以通过设置自定义RemoteAddressResolver
来定制解析远程地址的方式。
Spring Cloud Gateway提供了一个非默认远程地址解析器XForwardedRemoteAddressResolver,它基于x - forward - for报头。
XForwardedRemoteAddressResolver有两个静态构造函数方法,采用不同的安全方法:
XForwardedRemoteAddressResolver::trustAll
返回一个RemoteAddressResolver,它总是取x - forward - for报头中找到的第一个IP地址。
这种方法很容易被欺骗,因为恶意客户端可以为x - forward设置一个初始值——解析器会接受这个初始值。
XForwardedRemoteAddressResolver::maxTrustedIndex
获取与Spring Cloud Gateway前面运行的可信基础结构数量相关的索引。
例如Spring Cloud Gateway,只能通过HAProxy访问,那么应该使用1的值。如果在访问Spring Cloud Gateway之前需要两跳可信基础设施,那么应该使用值2。
给定以下标题值:
X-Forwarded-For: 0.0.0.1, 0.0.0.2, 0.0.0.3
下面的maxTrustedIndex值将产生以下远程地址。
使用JAVA配置:
GatewayConfig.java
RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
.maxTrustedIndex(1);
...
.route("direct-route",
r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
.uri("https://downstream1")
.route("proxied-route",
r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
.uri("https://downstream2")
)