# spring-cloud-gateway
**Repository Path**: cjbgitee/spring-cloud-gateway
## Basic Information
- **Project Name**: spring-cloud-gateway
- **Description**: spring-cloud-gateway学习
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: main
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 2
- **Created**: 2022-10-08
- **Last Updated**: 2024-06-03
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
[Spring Cloud Gateway Document](https://gitee.com/cjbgitee/spring-cloud-gateway/blob/main/docs/src/main/asciidoc/spring-cloud-gateway.adoc)
# 准备环境
> 环境依赖
- Maven
- Jdk17
- IdeaC 2022
> 官网地址
https://spring.io/projects/spring-cloud-gateway
> Fork地址
https://github.com/spring-cloud/spring-cloud-gateway.git
> 仓库地址
https://gitee.com/cjbgitee/spring-cloud-gateway.git
git@gitee.com:cjbgitee/spring-cloud-gateway.git
> 更新依赖
idea -settings - languages - kotlin - update
idea - maven - springCloudGateway - refresh
idea - maven - profiles - 选择 spring
> 运行示例
运行子模块 spring-cloud-gateway-sample 中 GatewaySampleApplication.main() 方法
```
# 运行结果
2022-10-09T10:43:14.822+08:00 DEBUG 12872 --- [ main] o.s.c.g.r.RouteDefinitionRouteLocator : RouteDefinition matched: default_path_to_httpbin
2022-10-09T10:43:14.829+08:00 DEBUG 12872 --- [ main] o.s.c.g.filter.GatewayMetricsFilter : New routes count: 2
2022-10-09T10:43:14.834+08:00 INFO 12872 --- [ main] o.s.c.g.sample.GatewaySampleApplication : Started GatewaySampleApplication in 7.074 seconds (process running for 7.761)
```
> Maven仓库
优先使用阿里云仓库下载依赖文件
其中有部分依赖的版本阿里云是没有的,需要从 `repo1` 下载
本项目对应 `4.0.0-SNAPSHOT` 的版本需要从项目 `profile.spring` 设置的仓库中下载
- 仓库配置:https://developer.aliyun.com/mvn/guide
- 查找依赖:https://developer.aliyun.com/mvn/search
- 设置 Maven jdk17
```bash
# mvn.cmd 首行添加
set JAVA_HOME=D:\Program\Apache\Jdk\jdk-17.0.3.1
```
> Maven命令
```bash
# 936 表示简体中文 GBK
# 65001 表示中文 UTF-8
chcp 65001
# 显示版本信息 --version
mvn -v
# 显示版本信息后继续执行Maven其他目标 --show-version
mnv -V
# 显示帮助信息 --help
mvn -h
# 日志级别,显示错误及相关信息 --errors
mvn -e
# 日志级别,显示调试信息 --debug
mvn -X
# 日志级别,仅显示错误信息 --quiet
mvn -q
# 激活profile,用逗号隔开
mvn -Pxxx
# 指定全局属性
mvn -Dxxx=yyy
# 不联网更新依赖,offline模式 --offline
mvn -o
# 仅构建当前模块,不构建子模块 --non-recursive
mvn -N
# 在指定模块上执行命令 --module_name
mvn -pl
# 遇到构建失败直接退出 --fail-fast
mvn -ff
# 无论结果如何,构建从不失败 --fail-never
mvn -fn
# 强制更新snapshot类型的插件或依赖库(否则maven一天只会更新一次)
mvn -U
# 强制更新显示错误及相关信息
mvn clean compile -U -e
# 不连网,不更新,显示错误及相关信息
mvn clean compile -o -e
# 编译项目通常使用
mvn clean compile -e
```
> Maven.settings
```xml
D:\Program\Apache\apache-maven-jar
aliyunmaven
central
aliyun-maven-repository
https://maven.aliyun.com/repository/public
jdk-17
true
17
17
17
17
UTF-8
UTF-8
UTF-8
maven2
maven2
maven2-maven-repository
https://repo1.maven.org/maven2
true
never
true
never
maven2
https://repo1.maven.org/maven2
maven2
```
> 版本依赖
Maven使用dependencyManagement定义依赖模块的默认版本后,子模块可以省略version
dependencyManagement只是申明,子模块使用时需要显示调用对应模块
项目模块依赖关系:
```
spring-cloud-gateway.parent -> spring-cloud-build(pom)
spring-cloud-build.dependencyManagement -> spring-cloud-build-dependencies(pom)
spring-cloud-build-dependencies.parent -> spring-boot-dependencies(pom)
```
`spring-boot-dependencies` 中的 `dependencyManagement` 模块定义了 `spring-boot-*` 默认的版本号
```
spring-cloud-gateway.dependencyManagement -> spring-cloud-commons-dependencies
```
`spring-cloud-commons-dependencies` 中的 `dependencyManagement` 模块定义了部分 `spring-cloud-*` 默认的版本号
# 运行机制
1. gateway 接受客户端请求
2. 客户端请求与路由进行匹配 Route
3. 请求经过Filter过滤链 Filter
4. 请求被转发至下游服务器并返回响应
5. 向客户端响应
# 基本组件
- Route
- AsyncPredicate
- GatewayFilter
- GatewayFilterChain
- GatewayAutoConfiguration
- GatewayProperties
- RouteDefinition
- FilterDefinition
- NameUtils
- PredicateDefinition
- RoutePredicateFactory
- GatewayFilterFactory
- RouteLocator
- RouteDefinitionLocator
- RouteDefinitionRouteLocator
- CompositeRouteDefinitionLocator
# 过滤器工厂

## AddRequestHeaderGatewayFilterFactory
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
filters:
- AddRequestHeader=X-Request-red, blue
```
> 变量配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeader=X-Request-Red, Blue-{segment}
```
## AddRequestHeadersIfNotPresent
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_request_headers_route
uri: https://example.org
filters:
- AddRequestHeadersIfNotPresent=X-Request-Color-1:blue,X-Request-Color-2:green
```
> 变量配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_request_header_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- AddRequestHeadersIfNotPresent=X-Request-Red:Blue-{segment}
```
## AddRequestParameterGatewayFilterFactory
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
filters:
- AddRequestParameter=red, blue
```
> 变量配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_request_parameter_route
uri: https://example.org
predicates:
- Host: { segment }.myhost.org
filters:
- AddRequestParameter=foo, bar-{segment}
```
## AddResponseHeaderGatewayFilterFactory
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
filters:
- AddResponseHeader=X-Response-Red, Blue
```
> 变量配置
```yaml
spring:
cloud:
gateway:
routes:
- id: add_response_header_route
uri: https://example.org
predicates:
- Host: { segment }.myhost.org
filters:
- AddResponseHeader=foo, bar-{segment}
```
## DedupeResponseHeaderGatewayFilterFactory
在网关cors和下游处理中添加了配置中定义的值时,此过滤器会删除响应请求头中对应的重复值
```yaml
spring:
cloud:
gateway:
routes:
- id: dedupe_response_header_route
uri: https://example.org
filters:
- DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
```
## SpringCloudCircuitBreakerFilterFactory
此过滤器将路由包装在断路器(`circuit breaker` 使用 `Spring Cloud CircuitBreaker APIs`)中
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker
```
> 使用fallbackUri,目前仅支持forward
断路器调用回调函数时跳转到 `/inCaseOfFailureUseThis` URI
```yaml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint
```
## FallbackHeadersGatewayFilterFactory
在转发到外部应用程序的请求头中添加 `CircuitBreaker` 执行异常信息
```yaml
spring:
cloud:
gateway:
routes:
- 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
filters:
- name: FallbackHeaders
args:
executionExceptionTypeHeaderName: Test-Header
```
## MapRequestHeaderGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: map_request_header_route
uri: https://example.org
filters:
- MapRequestHeader=Blue, X-Request-Red
```
## PrefixPathGatewayFilterFactory
给路由添加前缀
```yaml
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- PrefixPath=/mypath
```
## PreserveHostHeaderGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: preserve_host_route
uri: https://example.org
filters:
- PreserveHostHeader
```
## RequestRateLimiterGatewayFilterFactory
速率限制器,使用 `RateLimiter` 实现来确定是否允许当前请求继续,如果不是,则返回429
```yaml
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
```
## RedisRateLimiter
速率限制器的 Redis 实现
```yaml
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 # 请求token数
```
> 使用自定义速率限制器
```yaml
spring:
cloud:
gateway:
routes:
- id: requestratelimiter_route
uri: https://example.org
filters:
- name: RequestRateLimiter
args:
rate-limiter: "#{@myRateLimiter}"
key-resolver: "#{@userKeyResolver}"
```
## RedirectToGatewayFilterFactory
请求重定向,包含 `status` 和 `url` 参数,`status` 是300系列重定向 HTTP 代码
```yaml
spring:
cloud:
gateway:
routes:
- id: prefixpath_route
uri: https://example.org
filters:
- RedirectTo=302, https://acme.org
```
## RemoveJsonAttributesResponseBodyGatewayFilterFactory
从json正文根级别删除属性值
```yaml
spring:
cloud:
gateway:
routes:
- id: removejsonattributes_route
uri: https://example.org
filters:
- RemoveJsonAttributesResponseBody=id,color
```
> 递归删除属性
使用最后一个 boolean 型的参数指定从根级别递归删除属性
```yaml
spring:
cloud:
gateway:
routes:
- id: removejsonattributes_recursively_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- RemoveJsonAttributesResponseBody=id,color,true
```
## RemoveRequestHeaderGatewayFilterFactory
删除请求的请求头
```yaml
spring:
cloud:
gateway:
routes:
- id: removerequestheader_route
uri: https://example.org
filters:
- RemoveRequestHeader=X-Request-Foo
```
## RemoveResponseHeaderGatewayFilterFactory
删除请求返回值的请求头
```yaml
spring:
cloud:
gateway:
routes:
- id: removeresponseheader_route
uri: https://example.org
filters:
- RemoveResponseHeader=X-Response-Foo
```
## RemoveRequestParameterGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: removerequestparameter_route
uri: https://example.org
filters:
- RemoveRequestParameter=red
```
## RequestHeaderSizeGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: requestheadersize_route
uri: https://example.org
filters:
- RequestHeaderSize=1000B
```
## RewritePathGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: rewritepath_route
uri: https://example.org
predicates:
- Path=/red/**
filters:
- RewritePath=/red/?(?.*), /$\{segment}
```
## RewriteLocationResponseHeaderGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: rewritelocationresponseheader_route
uri: http://example.org
filters:
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
```
## RewriteResponseHeaderGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: rewriteresponseheader_route
uri: https://example.org
filters:
- RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***
```
## SaveSessionGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: save_session
uri: https://example.org
predicates:
- Path=/foo/**
filters:
- SaveSession
```
## SecureHeadersGatewayFilterFactory
> 禁用默认值使用以下配置
```properties
spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security
```
## SetPathGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: setpath_route
uri: https://example.org
predicates:
- Path=/red/{segment}
filters:
- SetPath=/{segment}
```
## SetRequestHeaderGatewayFilterFactory
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
filters:
- SetRequestHeader=X-Request-Red, Blue
```
> 变量配置
```yaml
spring:
cloud:
gateway:
routes:
- id: setrequestheader_route
uri: https://example.org
predicates:
- Host: { segment }.myhost.org
filters:
- SetRequestHeader=foo, bar-{segment}
```
## SetResponseHeaderGatewayFilterFactory
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: https://example.org
filters:
- SetResponseHeader=X-Response-Red, Blue
```
> 变量配置
```yaml
spring:
cloud:
gateway:
routes:
- id: setresponseheader_route
uri: https://example.org
predicates:
- Host: { segment }.myhost.org
filters:
- SetResponseHeader=foo, bar-{segment}
```
## SetStatusGatewayFilterFactory
> 基本配置
```yaml
spring:
cloud:
gateway:
routes:
- id: setstatusstring_route
uri: https://example.org
filters:
- SetStatus=UNAUTHORIZED
- id: setstatusint_route
uri: https://example.org
filters:
- SetStatus=401
```
> 添加请求代理的原始响应代码
```yaml
spring:
cloud:
gateway:
set-status:
original-status-header-name: original-http-status
```
## StripPrefixGatewayFilterFactory
从路径中去除部分参数
```yaml
spring:
cloud:
gateway:
routes:
- id: nameRoot
uri: https://nameservice
predicates:
- Path=/name/**
filters:
- StripPrefix=2
```
## RetryGatewayFilterFactory
该工厂支持以下参数:
- retries:可以重试的重试次数,默认为3
- statuses:可以重试的HTTP状态码
- methods:可以重试的HTTP方法,默认GET
- series:可以重试的状态码列表,默认 5XX
- exceptions:重试可以抛出的异常列表,默认 `IOExceptio/TimeoutException`
- backoff:默认disabled
- maxBackoff
- basedOnPreviousValue
```yaml
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
```
## RequestSizeGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: request_size_route
uri: http://localhost:8080/upload
predicates:
- Path=/upload
filters:
- name: RequestSize
args:
maxSize: 5000000
```
## SetRequestHostHeaderGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: set_request_host_header_route
uri: http://localhost:8080/headers
predicates:
- Path=/headers
filters:
- name: SetRequestHostHeader
args:
host: example.org
```
## TokenRelayGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: resource
uri: http://localhost:9000
predicates:
- Path=/resource
filters:
- TokenRelay=
```
## CacheRequestBodyGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: cache_request_body_route
uri: lb://downstream
predicates:
- Path=/downstream/**
filters:
- name: CacheRequestBody
args:
bodyClass: java.lang.String
```
## JsonToGrpcGatewayFilterFactory
```yaml
spring:
cloud:
gateway:
routes:
- id: json-grpc
uri: https://localhost:6565/testhello
predicates:
- Path=/json/**
filters:
- name: JsonToGrpc
args:
protoDescriptor: file:proto/hello.pb
protoFile: file:proto/hello.proto
service: com.example.grpcserver.hello.HelloService
method: hello
```
## Default Filters
```yaml
spring:
cloud:
gateway:
default-filters:
- AddResponseHeader=X-Response-Default-Red, Default-Blue
- PrefixPath=/httpbin
```
# 全局过滤器
##
# RouteDefinitionLocator
RouteDefinitionLocator 是路由定义定位器的顶级接口,用于读取路由的配置信息

## InMemoryRouteDefinitionRepository
InMemoryRouteDefinitionRepository 实现的接口 RouteDefinitionRepository 继承自
RouteDefinitionLocator和RouteDefinitionWriter
RouteDefinitionLocator 定义了对路由信息的获取操作
```java
public interface RouteDefinitionLocator {
Flux getRouteDefinitions();
}
```
RouteDefinitionWriter 定义了对路由的增加和删除操作
```java
public interface RouteDefinitionWriter {
Mono save(Mono route);
Mono delete(Mono routeId);
}
```
InMemoryRouteDefinitionRepository 实现了两个接口中对路由三种操作的定义
```java
public class InMemoryRouteDefinitionRepository implements RouteDefinitionRepository {
private final Map routes = synchronizedMap(new LinkedHashMap());
public Flux getRouteDefinitions() {
}
public Mono save(Mono route) {
}
public Mono delete(Mono routeId) {
}
}
```
RedisRouteDefinitionRepository 同样也是对这三种操作的实现
```java
public class RedisRouteDefinitionRepository implements RouteDefinitionRepository {
public Flux getRouteDefinitions() {
}
public Mono save(Mono route) {
}
public Mono delete(Mono routeId) {
}
}
```
## PropertiesRouteDefinitionLocator
从配置文件 yaml或properties 中读取路由配置信息
```java
public class PropertiesRouteDefinitionLocator implements RouteDefinitionLocator {
private final GatewayProperties properties;
public PropertiesRouteDefinitionLocator(GatewayProperties properties) {
}
public Flux getRouteDefinitions() {
}
}
```
## DiscoveryClientRouteDefinitionLocator
通过服务发现组件从注册中心获取服务信息,此时路由定义的源就是配置中心
## CachingRouteDefinitionLocator
缓存方式的路由定义定位器,通过传入路由定义定位器获取路由定义并缓存到本地
通过监听路由刷新时间RefreshRoutesEvent来刷新本地缓存的路由定义信息
## CompositeRouteDefinitionLocator
组合方式路由定义定位器使用组合模式进行实现,组合多个 RouteDefinitionLocator 的实现,为获取路由定义信息提供同一入口
## RouteDefinitionRouteLocatorTests
# Test用法
assertThat 会执行断言并返回 MapAssert 对象
> assertThat(source).containsAllEntriesOf(target)
判断 source 集合是否包含 target 集合的所有元素
# ADoc
ADoc(AsciiDoc)是和MarkDown一样的轻量级标记语言,IDEA安装插件即可查看
[ADoc和markdown比较](https://docs.asciidoctor.org/asciidoc/latest/asciidoc-vs-markdown/)
[ADoc说明文档](https://asciidoctor.org/docs/#the-basics)
# 其他说明
> maven packaging
- pom:父级项目,默认配置
- jar:子项目默认的打包类型
- war:需要部署的子项目打包类型
GAV(groupId, artifactId, version)
子模块不配置GAV会继承父级项目的GAV及其他默认配置
子模块只能使用jar或war打包,父级项目使用modules管理子模块
# 参考网址
[芋道源码:Spring-Cloud-Gateway](https://www.iocoder.cn/categories/Spring-Cloud-Gateway/)
[Java ProjectReactor框架之Flux篇](https://www.jianshu.com/p/8cb66e912641)