1、Spring Cloud Gateway 是什么
Spring Cloud Gateway是在Spring MVC之上构建API网关。Spring Cloud Gateway 旨在提供一种简单而有效的方法来路由到api,并为api提供横切关注点,比如:权限检验,监控,负载均衡等。
2、Spring Cloud Gateway特性
1)基于Spring5和SpringBoot2.0
2)能在任何请求属性上去匹配路由
3)通过predicate和filter 过滤和匹配路由
4)集成了Hystrix
5) 集成了服务发现
6)predicate和filter 易于编写
7)限流(RequestRateLimiterGatewayFilterFactory)
8)路径重写
3、术语
1)route
网关的基本构造块。它由一个ID、一个目标URI、一个predicate集合和一个filter集合定义。如果predicate为真,则匹配路由。
2)predicate
这是一个Java 8函数predicate。输入类型是Spring Framework ServerWebExchange。这使您可以匹配来自HTTP请求的任何内容,例如头或参数。
3)filter
使用特定工厂构造的Spring Framework GatewayFilter实例。在这里,可以在发送请求之前或之后修改请求和响应。
4、Spring Cloud Gateway架构图
客户端向Spring Cloud Gateway发出请求。如果网关handler mapping确定了一个请求与一个路由匹配,那么它将被发送到网关Web handler。handler通过特定于该请求的filter链运行该请求。过滤器被虚线分割的原因是过滤器可以在发送代理请求之前和之后运行逻辑。所有的“预”过滤器逻辑被执行。然后发出代理请求。发出代理请求后,将运行“post”筛选逻辑。
4、predicate配置
快捷配置
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
完全展开配置
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
predicate匹配在某个时间之前的请求
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
predicate匹配在某个时间之之后的请求
spring:
cloud:
gateway:
routes:
- id: after_route
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
predicate匹配cookie正则表达式
spring:
cloud:
gateway:
routes:
- id: cookie_route
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
predicate匹配请求头正则表达式(请求头有多个数字时匹配)
spring:
cloud:
gateway:
routes:
- id: header_route
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
predicate匹配主机名称
spring:
cloud:
gateway:
routes:
- id: host_route
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
predicate匹配请求方法
spring:
cloud:
gateway:
routes:
- id: method_route
uri: https://example.org
predicates:
- Method=GET,POST
predicate匹配url(使用{segment}来代替url变量)
spring:
cloud:
gateway:
routes:
- id: path_route
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
可以通过下面的方式来获取到segment变量的值
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
String segment = uriVariables.get("segment");
predicate匹配请求参数(当请求中带有green参数时匹配)
spring:
cloud:
gateway:
routes:
- id: query_route
uri: https://example.org
predicates:
- Query=green
predicate匹配ip地址
spring:
cloud:
gateway:
routes:
- id: remoteaddr_route
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
predicate根据权重匹配
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
5、内置网关过滤器
过滤器添加请求头
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}
过滤器删除请求头
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
过滤器添加请求参数
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=red, blue
过滤器删除请求参数
spring:
cloud:
gateway:
routes:
- id: removerequestparameter_route
uri: https://example.org
filters:
- RemoveRequestParameter=red
过滤器添加响应头
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Blue
过滤器添加url前缀 (/info 变成 /mypath/info)
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
过滤器限流
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 令牌桶每秒填充个数
redis-rate-limiter.burstCapacity: 20 # 令牌桶最大存储容量
redis-rate-limiter.requestedTokens: 1 # 每个请求消耗令牌数量
过滤器重定向
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- RedirectTo=302, https://acme.org
过滤器重写url(注意在yaml中$要写成 $\ , /red/blue 会被重写为 /bule)
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/red/**
filters:
- RewritePath=/red/(?<segment>.*),/blue/$\{segment}
过滤器重设url(/red/blue 会被重写为 /bule)
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: https://example.org
predicates:
- Path=/red/**
filters:
- SetPath=/{segment}
过滤器跳过url前缀(/name/blue/red 跳过前面两个前缀变成了 /red)
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: https://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
过滤器请求重试
backoff 为重试配置的指数后退。在返回间隔为firstBackoff * (factor ^ n)之后执行重试,其中n是迭代。如果配置了maxBackoff,则应用的最大backoff仅限于maxBackoff。如果basedOnPreviousValue为真,则使用prevBackoff *因子计算回退。
spring:
cloud:
gateway:
routes:
- id: retry_test
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3 # 重试次数
statuses: BAD_GATEWAY # 重试状态码
methods: GET,POST # 重试方法
backoff:
firstBackoff: 10ms # 第一次重试时间
maxBackoff: 50ms # 最大重试时间
factor: 2 # 重试时间因子
basedOnPreviousValue: false
过滤器限制请求大小
超过请求大小则会报错413,报错信息
errorMessage:
Request size is larger than permissible limit. Request size is 6.0 MB where permissible limit is 5.0 MB
spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
# 默认单位为B,可以使用KB,MB作为单位
maxSize: 5000000
过滤器修改请求实体
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_request_obj", r -> r.host("*.rewriterequestobj.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyRequestBody(String.class, Hello.class, MediaType.APPLICATION_JSON_VALUE,
(exchange, s) -> return Mono.just(new Hello(s.toUpperCase())))).uri(uri))
.build();
}
static class Hello {
String message;
public Hello() { }
public Hello(String message) {
this.message = message;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
过滤器修改响应实体
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("rewrite_response_upper", r -> r.host("*.rewriteresponseupper.org")
.filters(f -> f.prefixPath("/httpbin")
.modifyResponseBody(String.class, String.class,
(exchange, s) -> Mono.just(s.toUpperCase()))).uri(uri))
.build();
}
默认过滤器(适用于所有route)
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
6、配置
http超时配置
spring:
cloud:
gateway:
httpclient:
connect-timeout: 1000
response-timeout: 5s
跨域配置
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "*"
allowedMethods:
- GET