前言
Spring Cloud Gateway该项目提供了一个构建在 Spring 生态系统(包括 Spring 5, Spring Boot 2 ,Project Reactor)之上的 API 网关,旨在提供一种简单而有效的方法来路由到 api,并为它们提供横切关注点,例如: 安全性、监视 / 度量和弹性扩容。官方原文链接
1. 引入
要在项目中包含 Spring Cloud Gateway,请使用具有 org.springframework.cloud
组 ID 和 spring-cloud-starter-gateway
项目 ID 的 starter,如果包含了 starter,但不希望启用 gateway,请设置 spring.cloud.gateway.enabled=false
。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
注意:
1.Spring Cloud Gateway需要Spring Boot和Spring Webflux提供的Netty环境运行,所以不能在传统的servlet容器(tomcat,jboss)中或者war包的方式运行。
2. Spring Cloud Gateway是基于Spring Boot 2.x, Spring WebFlux, Project Reactor的响应式编程的,因此部分spring框架它上面可能不能工作(Spring Security ,spring data的mysql等传统数据库(Nosql可以使用))。如果不熟悉这些项目,建议首先阅读它们的文档,以便在使用 Spring Cloud Gateway 之前熟悉一些新概念。
2. 词汇
- Route:路由,网关的基本组件,它由一个 ID、一个目标 URI、一组Predicate和一组Filter组成。
- Predicate:断言: 这是Java 8新特性。输入类型是 Spring Framework ServerWebExchange,以匹配来自 HTTP 请求的任何内容,比如
header
或parameter
。 - Filter:过滤器。这些是 Spring Framework GatewayFilter 的实现,它们是用特定的工厂构建的。 这里,可以在发送下游请求之前或之后修改请求和响应。
3.工作流程
下面的图表概述了 Spring Cloud Gateway 的工作原理:
客户端向 Spring Cloud Gateway 网关发出请求。如果Gateway Handler Mapping
确定请求与路由匹配,则将其发送到Gateway Web Handler
。该Handler
通过特定于请求的过滤器链来运行请求。用虚线划分过滤器的原因是,过滤器可以在发送代理请求之前和之后运行逻辑。所有的前置过滤器执行完毕后,发出代理请求,最后执行后置过滤器。
注意:如果
route
的url
没有声明端口号,则使用http或者https的默认端口号。
4.配置路由断言和过滤器
有两种配置断言和过滤器的方法: 简洁方式和完全扩展的参数。 下面的大多数例子都使用了简洁方式。
名称和参数名称将在每个部分的第一个或两个句子中作为代码列出。 参数通常按快捷配置所需的顺序列出。
简易配置由固定的过滤器名称,后面跟着 =
和其他由,
隔开的参数构成。
application.yml
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
上面的示例使用两个参数定义了 Cookie
路由断言,这两个参数是 Cookie 名称(mycookie) 和与 mycookivalee 匹配的值。
完全展开的配置看起来更像带有名称 / 值
对的标准 yaml 配置。 通常,会有一个 name 键和一个 args 键。 args 用于配置断言或过滤器的键值对。
application.yml
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
上面两个例子分别展示了断言的简易配置和完全展开的配置。
5. 内置Predicates断言
After
路由断言只有一个ZonedDateTime生成的datetime参数,只有在这个事件之后的请求才能匹配上。
Example 1. application.yml
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
https://example.org这个地址在美国Denver时间2017-01-20 17:42:00之后才能
// 生成时间的代码
// demo 2020-05-06T19:16:43.338+08:00[Asia/Shanghai]
System.out.println(ZonedDateTime.now().toString());
Before
同样是一个时间断言,只不过是在配置的时间之前有效,过时之后失效。
Example 2. application.yml
spring:
cloud:
gateway:
routes:
- id: before_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
上面的链接地址在America/Denver时间2017-01-20 17:42::00之前有效
Between 路由断言,时间类断言,在声明的时间内有效。并且第二个时间必须大于第一个时间。
Example 3. application.yml
spring:
cloud:
gateway:
routes:
- id: between_route
uri: https://example.org
predicates:
- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
上面的链接在America/Denver时间2017-01 20日17时42-21日17时47分之间有效。
Cookie
断言有两个参数,一个cookie 名称和一个java 正则表达式,这个断言匹配给定的cookie 名和值正则匹配的请求。
Example 4. application.yml
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
上面的匹配那些请求中包含参数名为chocolate
并且值匹配ch.p
的请求。
Header
断言有两个参数,一个参数名,一个正则。只有当有这个参数并且值匹配正则的时候才能执行下去。
Example 5. application.yml
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
这个路由规则匹配Header
中包含X-Request-Id
并且值为纯数字的请求。
Host 路由断言接受一个正则域名列表,正则是用英文句号分割的Ant-Style
(ant 风格?)正则表达式。
Example 6. application.yml
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
这个路由匹配somehost.org
anotherhost.org
这两个域名下的所有请求。
Method
路由断言匹配一个或多个Http
请求方式(GET
POST
PUT
DELETE
HEAD
).
Example 7. application.yml
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
这个路由匹配所有的GET
POST
请求。
Path
路由断言接受两个参数:Spring PathMatcher
正则列表和一个名为 matchOptionalTrailingSeparator
的可选标志。
Example 8. application.yml
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
如果请求路径为(例如: / red / 1或 / red / blue 或 / blue / green) ,则此路由匹配。
这个断言提取了URL中模板变量(像前面例子中声明的segment
)组为key/value键值对放置在ServerWebExchange.getAttributes()
中,并用已经声明的ServerWebExchangeUtils.URI_TEMPLATE_VARIABLES_ATTRIBUTE
来声明。这些内容可被GatewayFilter
factories的一个名为get
的方法很简单的去访问。
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
Query
路由断言有两个参数: 一个必传参数 and 和一个可选的正则表达式。
Example 9. application.yml
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
如果一个请求中包含green的参数,则匹配成功。
application.yml
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=red, gree.
如果一个请求中包含参数red并且值匹配·gree.·这个正则,那么路由匹配。比如:green和greet。
RemoteAddr
路由断言接受一个来源地址的list,由IPv4或者IPv6组成,比如:192.168.0.1/16
(其中192.168.0.1
是IP地址,16
是子网掩码)
Example 10. application.yml
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
如果请求的远程地址是192.168.1.10,则此路由匹配。
权重路由断言接受两个参数:group
分组和Weight
权重。权重是按组计算的。
Example 11. application.yml
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% 的流量转发到 weighthigh. org,20% 的流量转发到 weighlow. org。
6. GatewayFilter 过滤器
路由过滤器允许以某种方式修改传入 HTTP 请求或传出 HTTP 响应。路由过滤器的作用域是特定的路由。Spring Cloud Gateway 包括许多内置的网关过滤器工厂。有关如何使用以下过滤器的更详细示例,请参阅unit tests 单元测试
AddRequestHeader
过滤器使用两个参数(name && value )
Example 13. application.yml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
这个路由所有匹配请求的下游请求的头部中添加了 X-Request-red: blue。AddRequestHeader
通常用户匹配请求路径或者host中的变量。下面的例子中会将诸如 https://xxx.org/red/snzz 中的 snzz
放入 X-Request-red
的value中。
Example 14. application.yml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}
6.2. AddRequestParameter 添加参数过滤器
AddRequestParameter
过滤器接受 name
和 value
参数
Example 15. application.yml
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=red, blue
上面的例子中为所有请求的下游请求的查询字符串red=blue
。
通常用于为指定请求路径或者域名的请求中添加请求参数,下面的例子中。会为myhost.org
域名下的所有请求加上一个参数,假如访问的是dev.myhost.org
,那么请求中就会加上一个foo=bar-dev
的参数。
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}
AddResponseHeader 采用 name
和 value
参数:
Example 17. application.yml
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Blue
这将为所有匹配请求的下游响应头添加 X-Response-Red: Bar
头。
通常用于为指定请求路径或者域名的请求响应的消息头添加参数,下面的例子中。会为myhost.org
域名下的所有请求响应体的头部加上一个参数,假如访问的是dev.myhost.org
,那么响应头中就会加上一个foo=bar-dev
的参数。
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddResponseHeader=foo, bar-{segment}
6.4 DedupeResponseHeader 去重响应过滤器
DedupeResponseHeader
接受一个name
参数和一个可选的strategy
参数。Name
可以包含以空格分隔的header
名称列表。
Example 19. application.yml
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
在网关 CORS 逻辑和下游逻辑都添加了Access-Control-Allow-Credentials
和Access-Control-Allow-Origin
响应头的情况下,这将删除重复的值。DedupeResponseHeader
过滤器还接受一个可选的策略参数。接受的值是 RETAIN_FIRST
(默认值:保留第一个)、 RETAIN_FIRST
(保留最后一个)和 RETAIN_UNIQUE
(保留唯一的)。
6.5 Spring Cloud CircuitBreaker
Spring Cloud 断路器网关过滤器工厂使用 Spring Cloud 断路器 api 将网关路由包裹在断路器中。 支持多个可以与 Spring 云网关一起使用的库。 Spring Cloud 开箱即用地支持Resilience4J
。
要启用 Spring Cloud CircuitBreaker 过滤器,需要将 Spring-Cloud-starter-CircuitBreaker-reactor-resilience4j
放在类路径上。
Example 20. application.yml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker
可以参考下面的API文档来配置这个断路器。Resilience4J Documentation
你可以声明spring.cloud.gateway.default-filters
来为所有的路由添加过滤器,这个属性是一个list。
Example 51. application.yml
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
上面的配置会为httpbin
请求路径下的请求的ResponseHeader
中加入参数X-Response-Default-Red=Default-Blue
。