1. 序言

Gateway配置文件非常强大,基本已经包含了大部分的使用场景,我们一般直接通过配置文件就可以完成配置了

2. 开启根据微服务名转发

1
spring.cloud.gateway.discovery.locator.enabled=true

开启此配置后会根据链接的path第一层寻找对应的微服务名,并且转发后会将第一层微服务名给去掉,保留后面的内容发给后续应用,
如: provider注册的服务名为CloudGatewayProvider,提供的服务路径为/providerController/hello,自身的servlet.context-path/cloud-provider,如图:

nacos
nacos

controller
controller

application.yml
application

通过访问以下路径可以得到provider数据,
类似于nginx的转发重写功能

1
localhost:8101/CloudGatewayProvider/cloud-provider/providerController/hello

3. 手动配置路由映射

此种方式手动配置路由映射,如:

1
2
3
4
5
6
7
8
spring:
cloud:
gateway:
routes:
- id: nacos-provider
uri: lb://CloudGatewayProvider
predicates:
- Path=/cloud-provider/**
  • id 配置的id为全局唯一,只要唯一就可以
  • uri 为访问的地址,即匹配到路径之后怎么转发
  • predicates 为匹配规则,上文是匹配到路径为/cloud-provider开头的所有请求都转发至微服务CloudGatewayProvider中,需要注意的是此种方式不会将匹配路径/cloud-provider舍弃

如上链接,访问地址可以改成

1
localhost:8101/cloud-provider/providerController/hello

与开启根据微服务名转发可以共存,互不影响。

4. 参数详解

Spring Cloud Gateway的主要功能之⼀是转发请求,转发规则的定义主要包含三个部分,如表所示。

定义 说明
Route(路由) 路由是⽹关的基本单元,由ID、URI、⼀组Predicate、⼀组Filter组成,根据Predicate进⾏匹配转发。
Predicate(谓语、断⾔) 路由转发的判断条件,⽬前SpringCloud Gateway⽀持多种⽅式,常⻅如:Path、Query、Method、Header等,写法必须遵循 key=vlue的形式
Filter(过滤器) 过滤器是路由转发请求时所经过的过滤逻辑,可⽤于修改请求、响应内容

4.1. Predicate 断⾔条件

规则解析

快捷配置:

规则 示例 说明
Path - Path=/gate/**,/rule/** 当请求的路径为gate、rule开头的时 生效
Before - Before=2017-01-20T17:42:47.789-07:00[Asia/Shanghai] 在时间之前的请求生效
After - After=2017-01-20T17:42:47.789- 07:00[Asia/Shanghai] 在时间之后的请求生效
Between - Between=2017-01-20T17:42:47.789-07:00[Asia/Shanghai],2017-01- 21T17:42:47.789-07:00[Asia/Shanghai] 在时间段之间的生效
Cookie - Cookie=id,[0-9] 【Cookie=cookie名, cookie值的正则表达式规则】
Header - Header=X-Request-Id, \d+ 【Header=header名, header值的正则表达式规则】
Host - Host=www.hd123.com 【Host=主机名(可配置多个,也可以使用通配符)】当主机名为www.hd123.com的时候生效
Method - Method=GET 只有GET方法生效
Query - Query=name, zhangsan 【Query=参数名,参数值】

完全解析:

上面其实都是简写的形式,还有完整的写法

1
2
3
4
5
6
7
predicates:
- Path=/cloud-provider/**,/cloud-provider2/**
- Cookie=mycookie,mycookievalue # 简写
- name: Cookie # 完整写法
args:
name: mycookie
regexp: mycookievalue

官方说明官网翻译

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
spring:
cloud:
gateway:
routes:
- id: after_route # 按照Cookie
uri: https://example.org
predicates:
- Cookie=mycookie,mycookievalue
- id: after_route # cookei的完全形式
uri: https://example.org
predicates:
- name: Cookie
args:
name: mycookie
regexp: mycookievalue
- id: after_route # 在时间之后
uri: https://example.org
predicates:
- After=2017-01-20T17:42:47.789-07:00[America/Denver]
- id: before_route # 在时间之前
uri: https://example.org
predicates:
- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
- 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]
- id: cookie_route # 按照cookie 正则匹配
uri: https://example.org
predicates:
- Cookie=chocolate, ch.p
- id: header_route # 按照请求头正则匹配
uri: https://example.org
predicates:
- Header=X-Request-Id, \d+
- id: host_route # 按照Host
uri: https://example.org
predicates:
- Host=**.somehost.org,**.anotherhost.org
- id: method_route # 按照方法类型
uri: https://example.org
predicates:
- Method=GET,POST
- id: path_route # 按照请求路径
uri: https://example.org
predicates:
- Path=/red/{segment},/blue/{segment}
- id: query_route ## 按照参数名有无
uri: https://example.org
predicates:
- Query=green
- id: query_route ## 按照参数名的值正则匹配
uri: https://example.org
predicates:
- Query=red, gree.
- id: remoteaddr_route # 按照远程地址
uri: https://example.org
predicates:
- RemoteAddr=192.168.1.1/24
- id: weight_high # 按照权重
uri: https://weighthigh.org
predicates:
- Weight=group1, 8
- id: weight_low
uri: https://weightlow.org
predicates:
- Weight=group1, 2

用到的断言器如下:

断言器

4.2. Filter

请求过滤器是gateway中强大的处理能力

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
spring:
cloud:
gateway:
routes:
- id: add_request_header_route # 添加请求头X-Request-red=blue
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
- id: add_request_header_route #请求头增加变量
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}

- id: add_request_parameter_route # 添加请求参数
uri: https://example.org
filters:
- AddRequestParameter=red, blue

- id: add_request_parameter_route # 添加带变量请求参数
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}

- id: add_response_header_route # 添加响应头
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Blue

- id: add_response_header_route # 添加带变量响应头
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- AddResponseHeader=foo, bar-{segment}

- id: dedupe_response_header_route # 删除重复数据 ??有点难理解
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
- id: hystrix_route # 开启Hystrix断路模式,需要引入spring-cloud-starter-netflix-hystrix依赖
uri: https://example.org
filters:
- Hystrix=myCommandName
- id: hystrix_route # 断路模式实现重写功能,即指定备用地址
uri: lb://backing-service:8088
predicates:
- Path=/consumingserviceendpoint
filters:
- name: Hystrix
args:
name: fallbackcmd
fallbackUri: forward:/incaseoffailureusethis
- RewritePath=/consumingserviceendpoint, /backingserviceendpoint
- id: ingredients # 重新路由到外部程序或控制处理程序
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: Hystrix
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
# 配置超时 hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000

- id: circuitbreaker_route # 配置熔断
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
- 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
- id: ingredients # 下面两个组成 工厂允许您在转发到外部应用程序的请求的标头中添加 Hystrix 或 Spring Cloud CircuitBreaker 执行异常详细信息fallbackUri
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

- id: map_request_header_route # Map请求头
uri: https://example.org
filters:
- MapRequestHeader=Blue, X-Request-Red

- id: prefixpath_route # 添加前缀 eg:请求/hello将被发送到/mypath/hello
uri: https://example.org
filters:
- PrefixPath=/mypath

- id: requestratelimiter_route # redis 限流器,使用令牌桶算法
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 用户每秒执行多少个请求,令牌桶被填满的速率
redis-rate-limiter.burstCapacity: 20 # 用户在一秒钟内允许执行的最大请求数,令牌桶可以容纳的令牌数量,此值设置为零会阻止所有请求
redis-rate-limiter.requestedTokens: 1 # 每个请求获取的令牌数量,默认1
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}" # 使用Spel表达式,此表示bean的名称为myRateLimiter
key-resolver: "#{@userKeyResolver}" # 使用Spel表达式,表示bean的名称为userKeyResolver

- id: prefixpath_route # 重定向过滤器
uri: https://example.org
filters:
- RedirectTo=302, https://acme.org #发送带有标头的状态 302 Location:https://acme.org以执行重定向。

- id: removerequestheader_route # 请求头删除过滤器
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo # 删除X-Request-Foo请求头

- id: removeresponseheader_route # 响应头删除过滤器
uri: https://example.org
filters:
- RemoveResponseHeader=X-Response-Foo

- id: removerequestparameter_route # 请求参数删除过滤器
uri: https://example.org
filters:
- RemoveRequestParameter=red

- id: rewritepath_route # 重写过滤器
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- RewritePath=/red(?<segment>/?.*), $\{segment} # /red/blue将路径设置为/blue 由于 YAML 规范,$应将 替换为。$\

- id: rewritelocationresponseheader_route
uri: http://example.org
filters:
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,

- id: rewriteresponseheader_route ## 响应头重写
uri: https://example.org
filters:
- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=*** #X-Response-Red设为空,密码设为***

- id: save_session ## session存储过滤器
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession #如果Spring Security与 Spring Session 集成,并希望确保安全详细信息已转发到远程进程,那么这一点至关重要。

- id: setpath_route # 路径重写过滤器
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- SetPath=/{segment}

- id: setrequestheader_route #设置请求头过滤器
uri: https://example.org
filters:
- SetRequestHeader=X-Request-Red, Blue
- id: setrequestheader_route #带变量的设置请求头过滤器
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- SetRequestHeader=foo, bar-{segment}

- id: setresponseheader_route #设置响应头过滤器
uri: https://example.org
filters:
- SetResponseHeader=X-Response-Red, Blue
- id: setresponseheader_route # 带参数的
uri: https://example.org
predicates:
- Host: {segment}.myhost.org
filters:
- SetResponseHeader=foo, bar-{segment}

- id: setstatusint_route # 设置响应码过滤器
uri: https://example.org
filters:
- SetStatus=401

- id: nameRoot # 抹去前几个参数过滤器
uri: https://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2 # 抹掉两个 请求/name/blue/red,到nameservice时变成 /red。

- id: retry_test # 重试过滤器
uri: http://localhost:8080/flakey
predicates:
- Host=*.retry.com
filters:
- name: Retry
args:
retries: 3 # 重试次数
statuses: BAD_GATEWAY # 需要重试的HTTP状态码,用 表示org.springframework.http.HttpStatus。
methods: GET,POST # 应该重试的HTTP方法,用 表示org.springframework.http.HttpMethod。
backoff: # 配置的重试指数
firstBackoff: 10ms # 重试执行 firstBackoff * (factor ^ n) n代表迭代次数
maxBackoff: 50ms # 配置了此表示应用最大指数为50ms
factor: 2
basedOnPreviousValue: false # 为true则 backoff = prevBackoff * factor

- id: request_size_route # 文件最大值过滤器
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000 #上传文件不能超过此值

用到的过滤器如下:

官方过滤器

除了指定具体的匹配对应的过滤器外,还可以指定全局过滤器

1
2
3
4
5
6
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin

4.2.1. SecureHeadersGatewayFilterFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
根据这篇博文中的建议,工厂SecureHeaders GatewayFilter在响应中添加了许多标头。

添加了以下标头(显示其默认值):
X-Xss-Protection:1 (mode=block)
Strict-Transport-Security (max-age=631138519)
X-Frame-Options (DENY)
X-Content-Type-Options (nosniff)
Referrer-Policy (no-referrer)
Content-Security-Policy (default-src 'self' https:; font-src 'self' https: data:; img-src 'self' https: data:; object-src 'none'; script-src https:; style-src 'self' https: 'unsafe-inline)'
X-Download-Options (noopen)
X-Permitted-Cross-Domain-Policies (none)
要更改默认值,请在命名空间中设置适当的属性spring.cloud.gateway.filter.secure-headers。可以使用以下属性:
xss-protection-header
strict-transport-security
x-frame-options
x-content-type-options
referrer-policy
content-security-policy
x-download-options
x-permitted-cross-domain-policies
要禁用默认值,请spring.cloud.gateway.filter.secure-headers.disable使用逗号分隔值设置属性。以下示例展示了如何执行此操作:
spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security

4.2.2. ModifyRequestBody 修改请求体过滤器

请求传下去时修改请求体,该过滤器只能使用 Java DSL 进行配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@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;
}
}

4.2.3. ModifyRequestBody 修改响应体过滤器

1
2
3
4
5
6
7
8
9
@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();
}

4.2.4. GlobalFilter 全局过滤器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Bean
public GlobalFilter customFilter() {
return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
log.info("custom global filter");
return chain.filter(exchange);
}

@Override
public int getOrder() {
return -1;
}
}

从exchange中可以拿到很多东西

globle

LoadBalancerClientFilter 负载均衡过滤器

处理配置文件中的 uri: lb://service-namae

WebsocketRoutingFilter websoket过滤器

处理配置文件中的 uri: ws://service-namae

5. CORS跨域处理配置

1
2
3
4
5
6
7
8
9
spring:
cloud:
gateway:
globalcors:
cors-configurations:
'[/**]':
allowedOrigins: "https://docs.spring.io"
allowedMethods:
- GET

官方文档google翻译:

cors

6. 官方配置文件

https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.2.RELEASE/reference/html/appendix.html

7. Actuator 配置

1
2
3
4
# 默认开启
management.endpoint.gateway.enabled=true
# web中需要添加此选项才能访问gateway路径
management.endpoints.web.exposure.include=gateway

http://localhost:8101/actuator/gateway/routes