Spring Cloud Gateway官方文档学习笔记
前言
- 基础知识:API网关基础知识总结
- 面试题:Spring Cloud
Gateway夺命连环10问?
何为网关?
什么是网关?理解成火车站的检票口,统一 检票
网关优点: 统一进行操作,去处理一些问题
1、网关作用
- 路由
- 负载均衡
- 统一鉴权
- 统一处理跨域
- 统一业务处理(缓存)
- 访问控制
- 发布控制
- 流量染色
- 统一接口保护
- 限制请求
- 信息脱敏
- 降级(熔断)
- 限流 学习令牌桶算法,学习露桶算法,学习一下 RedislimitHandler
- 超时时间
- 重试(业务保护)
- 统一日志
- 统一文档
2、具体作用
路由(请求转发)
起到转发的作用,比如有接口 A 和接口 B, 网关会记录这些信息,根据用户访问的地址和参数,转发请求到对应的接口(服务器 / 集群)
用户 a 调用接口 A
/a => 接口 A
/b => 接口 B
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
负载均衡
在路由的基础上可以转发到某一个服务器
/c => 服务A / 集群 A(随机转发到其中的某一个机器)
uri 从固定地址改成 b:xx
统一鉴权
判断用户是否有权限进行操作,无论访问什么接口,我都统一去判断权限,不用重复写
统一处理跨域
网关统一处理跨域,不用在每个项目单独处理
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#cors-configuration
统一业务处理
把每个项目中都要做的通用逻辑放到上层(网关),统一处理,比如本项目的次数统计
访问控制
黑白名单,比如限制 DDOS IP – 将已知的恶意 IP 地址添加到黑名单中,从而防止这些 IP 地址对系统发起 DDoS 攻击。
黑白名单是一种常见的网络安全策略,用于限制或允许 特定的 IP 地址或 IP 地址范围 访问网络资源。限制 DDoS(分布式拒绝服务攻击)IP 是黑名单的一个典型用例。
发布控制
灰度发布,比如上线新接口,先给新接口分配 20%流量,老接口80%,再慢慢调整比例
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-weight-route-predicate-factory
流量染色
区分用户来源
给请求(流量)添加一些标识,一般是设置请求头中,添加新的请求头
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-addrequestheader-gatewayfilter-factory
全局染色:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#default-filters
接口保护
-
限制请求
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#requestheadersiz-gatewayfilter-factory
-
信息脱敏
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-removerequestheader-gatewayfilter-factory
-
降级(熔断)进行兜底
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#fallback-headers
-
限流
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-requestratelimiter-gatewayfilter-factory
-
超时时间 超时就中断
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#http-timeouts-configuration
-
重试(业务保护):
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-retry-gatewayfilter-factory
统一日志
统一的请求,响应信息记录
统一文档
将下游项目的文档进行聚合,在一个页面统一查看
建议用:https://doc.xiaominfo.com/docs/middleware-sources/aggregation-introduction
网关的分类
- **全局网关(接入层网关)**作用是负载均衡、请求日志等,不和业务逻辑绑定
- **业务网关(微服务网关)**会有一些业务逻辑,作用是将请求转发到不同的业务/项目/接口/服务
参考文章:https://blog.csdn.net/qq_21040559/article/details/122961395
实现
- Nginx (全局网关),Kong网关(API网关), 编程成本相对较高
- Spring Cloud Gateway(取代了Zuul)性能高 可以用java代码来写逻辑 适于学习
网关技术选型:https://zhuanlan.zhihu.com/p/500587132
Spring Cloud Gateway
全部内容基本来自官网
官网:https://spring.io/projects/spring-cloud-gateway
官方文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference//html/
中文文档:https://springdoc.cn/spring-cloud-gateway/#gateway-starter
新建项目
在 IDEA 中新建项目 勾选 Gateway、Lombok
参考官网 get started 中的实例代码
@SpringBootApplication
public class DemogatewayApplication {@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route("path_route", r -> r.path("/get").uri("http://httpbin.org")).route("host_route", r -> r.host("*.myhost.org").uri("http://httpbin.org")).route("rewrite_route", r -> r.host("*.rewrite.org").filters(f -> f.rewritePath("/foo/(?<segment>.*)", "/${segment}")).uri("http://httpbin.org")).route("hystrix_route", r -> r.host("*.hystrix.org").filters(f -> f.hystrix(c -> c.setName("slowcmd"))).uri("http://httpbin.org")).route("hystrix_fallback_route", r -> r.host("*.hystrixfallback.org").filters(f -> f.hystrix(c -> c.setName("slowcmd").setFallbackUri("forward:/hystrixfallback"))).uri("http://httpbin.org")).route("limit_route", r -> r.host("*.limited.org").and().path("/anything/**").filters(f -> f.requestRateLimiter(c -> c.setRateLimiter(redisRateLimiter()))).uri("http://httpbin.org")).build();}
}
编写代码:
@SpringBootApplication
public class XuanapiGatewayApplication {public static void main(String[] args) {SpringApplication.run(XuanapiGatewayApplication.class, args);}// 构建自定义路由@Beanpublic RouteLocator customRouteLocator(RouteLocatorBuilder builder) {return builder.routes().route("to_baidu", r -> r.path("/baidu") // 定义路由名称为 "to_baidu".uri("http://www.baidu.com/")) // 将匹配的请求转发到 "http://www.baidu.com/".build();}}
在此配置类中,定义了一个名为 "to_baidu"
的路由规则,当请求的路径是 "/baidu"
时,将被路由到 “http://www.baidu.com/”。
1、核心概念
Glossary
官方文档如下
- Route: The basic building block of the gateway. It is defined by an ID, a destination URI, a collection of predicates, and a collection of filters. A route is matched if the aggregate predicate is true.
- Predicate: This is a Java 8 Function Predicate. The input type is a Spring Framework
ServerWebExchange
. This lets you match on anything from the HTTP request, such as headers or parameters. - Filter: These are instances of
GatewayFilter
that have been constructed with a specific factory. Here, you can modify requests and responses before or after sending the downstream request.
解析:
-
路由(根据什么条件,转发到哪里)
-
谓词 / 断言(一组规则,条件,用来确定如何转发路由)
-
过滤器:对请求进行一系列的处理,比如添加请求头,添加请求参数
请求流程
- 客户端发起请求
- Handler Mapping:根据断言,去将请求转发到对应的路由
- Web Handler:处理请求(一层层经过过滤器)
- 实际调用服务
2、两种配置方式
-
配置式 (方便,规范)能用就用
- 简化版
spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- Cookie=mycookie,mycookievalue
- 全称
spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- name: Cookieargs:name: mycookieregexp: mycookievalue
-
编程式(灵活,相对麻烦) – 就是自己编写代码定义
3、路由的各种断言
官网地址: https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gateway-request-predicates-factories
目录
- After 在xx时间之后
- Before 在xx时间之前
- Between 在xx时间之间
- 请求类别
- 请求头(包含Cookie)
- 查询参数
- 客户端地址
- 权重
After
The After Route Predicate Factory
当前时间在这个时间之后,就会访问当前这个路由
spring:cloud:gateway:routes:- id: after_routeuri: https://example.orgpredicates:- After=2017-01-20T17:42:47.789-07:00[America/Denver]
Before
The Before Route Predicate Factory
当前时间在这个时间之前,就会访问当前这个路由
spring:cloud:gateway:routes:- id: before_routeuri: https://example.orgpredicates:- Before=2017-01-20T17:42:47.789-07:00[America/Denver]
Between
The Between Route Predicate Factory
当前时间在这个时间之间,就会访问当前这个路由
spring:cloud:gateway:routes:- id: between_routeuri: https://example.orgpredicates:- Between=2017-01-20T17:42:47.789-07:00[America/Denver], 2017-01-21T17:42:47.789-07:00[America/Denver]
请求头(包含Cookie)
The Cookie Route Predicate Factory
如果你的请求头cookie的是chocolate,它的值是ch.p,就会访问当前这个路由
spring:cloud:gateway:routes:- id: cookie_routeuri: https://example.orgpredicates:- Cookie=chocolate, ch.p
The Header Route Predicate Factory
如果你的请求头包含 X-Request-Id
这样一个请求头,并且,它的值符合正则表达式的规则,就会访问当前这个路由
spring:cloud:gateway:routes:- id: header_routeuri: https://example.orgpredicates:- Header=X-Request-Id, \d+
域名
The Host Route Predicate Factory
如果你的访问的是这个 **.somehost.org,.anotherhost.org
,域名,就会访问当前这个路由
spring:cloud:gateway:routes:- id: host_routeuri: https://example.orgpredicates:- Host=**.somehost.org,**.anotherhost.org
请求类别
The Method Route Predicate Factory
如果你的请求类别是这个 GET、POST,就会访问当前这个路由
spring:cloud:gateway:routes:- id: method_routeuri: https://example.orgpredicates:- Method=GET,POST
访问的地址
The Path Route Predicate Factory
如果你的访问的地址是以这些 /red/{segment},/blue/{segment}
路径作为前缀,就会访问当前这个路由({segment}
花括号定义占位符)
spring:cloud:gateway:routes:- id: path_routeuri: https://example.orgpredicates:- Path=/red/{segment},/blue/{segment}
参考:https://springdoc.cn/spring-cloud-gateway/#path
查询参数
The Query Route Predicate Factory
根据查询条件,比如 red greet green,就会访问当前这个路由
spring:cloud:gateway:routes:- id: query_routeuri: https://example.orgpredicates:- Query=red, gree.
远程地址
The RemoteAddr Route Predicate Factory
根据远程地址,比如你的用户的 ip地址是 192.168.1.1/24,就会访问当前这个路由
spring:cloud:gateway:routes:- id: remoteaddr_routeuri: https://example.orgpredicates:- RemoteAddr=192.168.1.1/24
权重
The Weight Route Predicate Factory
根据你设置的权重,给你把同一个访问的地址,重定到不同的服务,轻松实现发布控制
spring:cloud:gateway:routes:- id: weight_highuri: https://weighthigh.orgpredicates:- Weight=group1, 8- id: weight_lowuri: https://weightlow.orgpredicates:- Weight=group1, 2
XForwarded 远程地址
The XForwarded Remote Addr Route Predicate Factory
从请求头中如果拿到 XForwarded 这个请求头的地址 192.168.1.1/24 就会访问当前这个路由
spring:cloud:gateway:routes:- id: xforwarded_remoteaddr_routeuri: https://example.orgpredicates:- XForwardedRemoteAddr=192.168.1.1/24
4、过滤器
官网文档:https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#gatewayfilter-factories
基本功能:对请求头、请求参数、响应头的增删改查
1.添加请求求头
2.添加请求参数
3.添加响应头
4.降级
5.限流
6.重试
增加请求头(可以用作流量染色)
The AddRequestHeader
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: add_request_header_routeuri: https://example.orgfilters:- AddRequestHeader=X-Request-red, blue
增加请求参数
The AddRequestParameter
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: add_request_parameter_routeuri: https://example.orgfilters:- AddRequestParameter=red, blue
这将为所有匹配的请求在下游请求的查询字符串中添加 red=blue
。
添加响应头
The AddResponseHeader
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: add_response_header_routeuri: https://example.orgfilters:- AddResponseHeader=X-Response-Red, Blue
这将把 X-Response-Red:Blue
header 添加到所有匹配请求的下游响应的 header 中。
如果响应头中有重复的,去重
The DedupeResponseHeader
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: dedupe_response_header_routeuri: https://example.orgfilters:- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
保留策略:第一,最后,随机
The DedupeResponseHeader
filter also accepts an optional strategy
parameter. The accepted values are RETAIN_FIRST
(default), RETAIN_LAST
, and RETAIN_UNIQUE
.
在 Spring Cloud Gateway 的 DedupeResponseHeader 过滤器中,可以使用 strategy 参数来指定响应头的保留策略。该过滤器的作用是去重响应头,确保在多次请求后只保留一个相同的响应头。
可接受的 strategy 参数值有三种:
-
RETAIN_FIRST:默认值。表示保留第一个出现的响应头,后续相同的响应头会被忽略,只保留第一个。
-
RETAIN_LAST:表示保留最后一个出现的响应头,之前的相同响应头会被忽略,只保留最后一个。
-
RETAIN_UNIQUE:表示保留所有不重复的响应头,不论其出现的顺序。
通过设置不同的保留策略,可以控制响应头的去重方式,以满足具体的需求。默认情况下,使用 RETAIN_FIRST 策略,保留第一个出现的响应头。
降级
Spring Cloud CircuitBreaker GatewayFilter Factory
需要引入 spring-cloud-starter-circuitbreaker-reactor-resilience4j
包
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-circuitbreaker-reactor-resilience4j</artifactId>
</dependency>
spring:cloud:gateway:routes:- id: circuitbreaker_routeuri: lb://backing-service:8088predicates:- Path=/consumingServiceEndpointfilters:- name: CircuitBreakerargs:name: myCircuitBreakerfallbackUri: forward:/inCaseOfFailureUseThis- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
这个路由规则定义了一个对 “/consumingServiceEndpoint” 路径的请求转发到名为 “backing-service” 的服务的 8088 端口。同时,还使用了熔断器来保护后端服务,当后端服务发生故障时,会使用 “/inCaseOfFailureUseThis” 作为回退 URI,以保证系统的稳定性和可用性。
降级处理器,写一下降级规则
The FallbackHeaders
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: ingredientsuri: lb://ingredientspredicates:- Path=//ingredients/**filters:- name: CircuitBreakerargs:name: fetchIngredientsfallbackUri: forward:/fallback- id: ingredients-fallbackuri: http://localhost:9994predicates:- Path=/fallbackfilters:- name: FallbackHeadersargs:executionExceptionTypeHeaderName: Test-Header
-
id: ingredients: 这个路由规则的唯一标识符为 “ingredients”。
-
uri: lb://ingredients: 当请求匹配到该路由规则时,它会被转发到名为 “ingredients” 的服务。“lb://” 是 Spring Cloud Gateway 中定义的 LoadBalancer URI Scheme,表示通过负载均衡方式选择后端服务。
-
predicates: 这里使用 Path 断言器,表示请求的路径必须以 “/ingredients/” 开头时,才会匹配到这个路由规则。
-
filters: 这里定义了一个过滤器。
-
CircuitBreaker: 这是 Spring Cloud Gateway 的熔断器过滤器,它用于实现熔断机制。在这个配置中,指定了一个名为 “fetchIngredients” 的熔断器,当后端服务发生故障时,将会使用 “/fallback” 作为备用的回退 URI。
id: ingredients-fallback: 这个路由规则的唯一标识符为 “ingredients-fallback”。 -
uri: http://localhost:9994: 当请求匹配到该路由规则时,它会被转发到 “http://localhost:9994”,即本地的另一个服务。
-
predicates: 这里使用 Path 断言器,表示请求的路径必须为 “/fallback” 时,才会匹配到这个路由规则。
-
filters: 这里定义了一个过滤器。
-
FallbackHeaders: 这是一个自定义的过滤器,用于在请求发生回退时设置响应头信息。在这个配置中,指定了响应头中的 “Test-Header” 字段为 “executionExceptionTypeHeaderName”,用于标识回退的原因类型。
API 网关中的降级和熔断功能主要体现在以下几个方面:
- 降级处理:当后端服务出现异常或不可用时,API 网关可以根据事先定义的降级策略,临时关闭或限制某些功能或服务,以保证核心功能的正常运行。例如,当某个微服务不可用时,可以返回预先设定的默认值或错误信息,而不是将错误暴露给用户。
- 熔断机制:在后端服务出现持续性故障或高错误率时,API 网关可以自动触发熔断机制,暂时关闭对该服务的请求转发,并快速返回预先设定的错误响应。这样可以避免请求大量失败导致雪崩效应,保护其他服务和系统的正常运行。
- 限流控制:API 网关可以根据后端服务的处理能力和负载情况,对请求进行限流控制,防止后端服务被过多请求压垮。通过限流,可以保证服务的稳定性和可用性,防止系统过载。
- 服务降级:当后端服务出现异常或高负载时,API 网关可以通过服务降级,临时关闭或替换某些不重要或资源消耗较大的服务,以保障核心功能的稳定运行。
- 异常处理:API 网关可以对后端服务返回的异常进行统一处理,将错误信息转换成统一的格式,并返回给客户端。这样可以提供更好的用户体验,并帮助开发团队及时发现和解决问题。
映射
The MapRequestHeader
GatewayFilter
Factory
如果你的 请求头 里面有 Blue,会把 Blue 的值给 X-Request-Red,相当于做了映射
spring:cloud:gateway:routes:- id: map_request_header_routeuri: https://example.orgfilters:- MapRequestHeader=Blue, X-Request-Red
前缀处理器
The PrefixPath
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: prefixpath_routeuri: https://example.orgfilters:- PrefixPath=/mypath
这会将 /mypath
作为所有匹配请求的路径的前缀。因此,对 /hello
的请求将发送到 /mypath/hello
。
固定 Host
The PreserveHostHeader
GatewayFilter
Factoryatewayfilter-factory
请求头转发的时候,有时候 host值 会变,这个可以保证不变
spring:cloud:gateway:routes:- id: preserve_host_routeuri: https://example.orgfilters:# 用于保留请求中的Host头信息。- PreserveHostHeader
限流
The RequestRateLimiter
GatewayFilter
Factory
一般会使用 redis+令牌桶算法
spring:cloud:gateway:routes:- id: requestratelimiter_routeuri: https://example.orgfilters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 10redis-rate-limiter.burstCapacity: 20redis-rate-limiter.requestedTokens: 1
限制请求头大小
RequestHeaderSize
GatewayFilter
Factory
请求保护
spring:cloud:gateway:routes:- id: requestheadersize_routeuri: https://example.orgfilters:- RequestHeaderSize=1000B
移除请求头(脱敏)
The RemoveRequestHeader Gateway Filter Factory
spring:cloud:gateway:routes:- id: removerequestheader_routeuri: https://example.orgfilters:- RemoveRequestHeader=X-Request-Foo
This removes the X-Request-Foo
header before it is sent downstream.
这将在发送到下游之前删除 X-Request-Foo
标头。
改写特殊的请求参数
The RewritePath
GatewayFilter
Factory
spring:cloud:gateway:routes:- id: rewritepath_routeuri: https://example.orgpredicates:- Path=/red/**filters:- RewritePath=/red/?(?<segment>.*), /$\{segment}
这个配置中定义了一个路由规则,它会将所有以 “/red/” 开头的请求转发到 “https://example.org”,并将 “/red/” 后面的路径作为子路径添加到目标 URI 上,实现了路径重写的功能。例如,对于请求 “/red/test”,将被转发到 “https://example.org/test”。
重试接口
The Retry GatewayFilter
Factory
自动帮你重试接口,降级重试
spring:cloud:gateway:routes:# 定义一个名为"retry_test"的路由规则- id: retry_test# 转发到"http://localhost:8080/flakey"的目标URLuri: http://localhost:8080/flakeypredicates:# 当请求的Host为任意子域名.retry.com时,匹配该路由规则- Host=*.retry.comfilters:# 定义一个重试过滤器- name: Retryargs:# 当请求失败时,最多重试3次(包括初始请求)retries: 3# 定义需要重试的HTTP状态码,这里设置为BAD_GATEWAYstatuses: BAD_GATEWAY# 定义需要重试的HTTP请求方法,这里设置为GET和POSTmethods: GET,POST# 定义重试的时间间隔策略backoff:# 第一次重试的时间间隔为10毫秒firstBackoff: 10ms# 最大重试时间间隔为50毫秒maxBackoff: 50ms# 重试时间间隔的增长因子,每次重试的时间间隔将是上一次的倍数factor: 2# 这里设置为false,表示每次重试的时间间隔都是根据初始值来计算的,而不是上一次重试的值basedOnPreviousValue: false
这个配置中定义了一个路由规则,它会将所有 Host 为任意 子域名.retry.com
的请求转发到 “http://localhost:8080/flakey”,并在请求失败时进行最多 3 次的重试,重试的时间间隔为 10ms、20ms 和 40ms,最大不超过 50ms,仅对 GET 和 POST 方法的请求进行重试,并且仅在返回的 HTTP 状态码为 BAD_GATEWAY 时进行重试。
目的
- 重试的目的是为了在网络不稳定或服务不可用的情况下,尝试重新发送请求,以增加请求成功的机会。
- 通过重试,可以在一定程度上提高请求的成功率,减少因为临时性的网络问题或服务故障而导致的请求失败。
默认过滤器
Default Filters
- 可以用作全局染色
spring:cloud:gateway:default-filters: # 设置默认的过滤器- AddResponseHeader=X-Response-Default-Red, Default-Blue # 添加响应头的过滤器,给响应头添加 X-Response-Default-Red 和 Default-Blue 两个字段- PrefixPath=/httpbin # 前缀路径过滤器,给请求路径添加前缀 /httpbin
全局染色:在这里,它添加了一个名为 X-Response-Default-Red
的响应头,并设置其值为 Default-Blue
。
5、其他配置
1、全局过滤器
Global Filters
自定义过滤器
@Bean
public GlobalFilter customFilter() {return new CustomGlobalFilter();
}public class CustomGlobalFilter implements GlobalFilter, Ordered {@Overridepublic Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {log.info("custom global filter");return chain.filter(exchange);}@Overridepublic int getOrder() {return -1;}
}
2、Http timeouts configuration
Global timeouts
配置 http 超时
spring:cloud:gateway:httpclient:connect-timeout: 1000response-timeout: 5s
3、CORS Configuration
跨域配置
spring:cloud:gateway:globalcors: # 全局CORS跨域配置cors-configurations: # 定义跨域配置'[/**]': # 匹配所有路径allowedOrigins: "https://docs.spring.io" # 允许的来源(域名),这里只允许来自 https://docs.spring.io 的请求allowedMethods: # 允许的HTTP
对于所有 GET 请求的路径,允许来自 docs.spring.io
的请求的 CORS(跨源资源共享)请求。