# spring-cloud-gateway **Repository Path**: dada980122/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**: 0 - **Forks**: 2 - **Created**: 2022-12-20 - **Last Updated**: 2022-12-20 ## 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 # 过滤器工厂 ![gateway-filter](spring-cloud-gateway-server/diagram/gateway-filter.png) ## 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 是路由定义定位器的顶级接口,用于读取路由的配置信息 ![RouteDefinitionLocator](images/RouteDefinitionLocator.png) ## 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)