目录

Spring Cloud Gateway

1.1 简介

内置的过滤器工厂

4.1快捷配置

4.2 完全扩展的参数

5.Rote Predicate Factories 路由断言

5.1After Rote Predicate 在断言之后

5.2 Before Rote Predicate 在断言之前

5.3 Between Route 中间

The Cookie Route Predicate 使用cookie

The Header Route Predicate 断言使用header

5.6 The Host Route Predicate 断言使用host

5.7 The Method Route Predicate

5.8. The Path Route Predicate Factory 路径断言

5.9. The Query Route Predicate Factory 查询断言

5.10. The RemoteAddr Route Predicate Factory 远程路径

5.11. The Weight Route Predicate Factory 权重

5.11.1. Modifying the Way Remote Addresses Are Resolved

6.GatewayFilter Factories 网关过滤

6.1 The AddRequestHeader GatewayFilter Factory

6.2 The AddRequestParameter GatewayFilter Factory

6.3 The AddResponseHeader GatewayFilter Factory 响应头

6.4The DedupeResponseHeader GatewayFilter Factory 过滤重复响应头

6.5 The Hystrix GatewayFilter Factory 熔断

6.6. Spring Cloud CircuitBreaker GatewayFilter Factory

6.6.1. Tripping The Circuit Breaker On Status Codes 返回状态

6.7. The FallbackHeaders GatewayFilter Factory

6.8 The MapRequestHeader GatewayFilter Factory

6.9 The PrefixPath GatewayFilter Factory 路径前缀

6.10 The PreserveHostHeader GatewayFilter Factory

6.11. The RequestRateLimiter GatewayFilter Factory 请求速率限制

spring cloud gateway 自带了个限流器filter,就是RequestRateLimiter,可以使用令牌桶算法来限流

首先看下spring cloud gateway的配置,注意要用到redis

这个key resolver会生成一个key,为这个key生成一个令牌桶。如果是客户端ip,那么就是为每个ip生成一个令牌桶。如果是个固定值,就是全局的令牌桶。

6.11.1 The Redis RateLimiter

6.12 The RedirectTo GatewayFilter Factory 重定向

6.13 The RevoveRequestHeader GatewayFilter Factory

6.14 RemoveResponseHeader Gateway Factory

6.15 The RemoveRequestParamter GatewayFilter Factory

6.16 The RewritePath GatewayFilter Factory 重写路径

6.18 RewriteLocationResonseHeader GateWayFilter Factory 重写响应头中 Location 的值

6.18. The RewriteResponseHeader GatewayFilter Factory

6.19. The SaveSession GatewayFilter Factory

6.20. The SecureHeader GatewayFilter Factory unknow

6.21 The SetPath GatewayFilter Factory 修改路径

6.22 The SetRequestHeader GatewayFilter Factory

6.23. The SetResponseHeader GatewayFilter Factory 设置响应头

6.24 The SetStatus GatewayFilter Factory

6.25 The StripPrefix GatewayFilter Factory 剥离路径

6.26. The Retry GatewayFilter Factory 重试

6.27. The RequestSize GatewayFilter Factory

6.28. The SetRequestHostHeader GatewayFilter Factory

6.29. Modify a Request Body GatewayFilter Factory 修改请求体

6.30. Modify a Response Body GatewayFilter Factory 想改响应体

6.31. Default Filter 默认过滤

7. Global Filters 全局过滤

7.1 Combined Global Filter and GatewayFilter Ordering 组合全局过滤器和网关过滤器排序

7.2. Foward Routing Filter

7.3. The LoadBalancerClient Filter

7.4. The ReactiveLoadBalancerClientFilter

7.5.The Netty Routing Filter --了解

7.6. The Netty Write Response Filter 将代理响应写回网关的客户端侧--了解

7.7. The RouteToRequestUrl Filter --将从request里获取的原始url转换成Gateway进行请求转发时所使用的url

7.8. The Websocket Routing Filter --- 使用Spring Web Socket将转发 Websocket 请求

7.9. The Gateway Metrics Filter 监控指标

1.1 简介

SpringCloud Gateway 是 Spring Cloud 的一个全新项目,该项目是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等技术开发的网关,它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。

SpringCloud Gateway 作为 Spring Cloud 生态系统中的网关,目标是替代 Zuul,在Spring Cloud 2.0以上版本中,没有对新版本的Zuul 2.0以上最新高性能版本进行集成,仍然还是使用的Zuul 2.0之前的非Reactor模式的老版本。而为了提升网关的性能,SpringCloud Gateway是基于WebFlux框架实现的,而WebFlux框架底层则使用了高性能的Reactor模式通信框架Netty。

Spring Cloud Gateway 的目标,不仅提供统一的路由方式,并且基于 Filter 链的方式提供了网关基本的功能,例如:安全,监控/指标,和限流。

提前声明:Spring Cloud Gateway 底层使用了高性能的通信框架Netty

1.引入Geteway

<span style="background-color:#f8f8f8"><span style="color:#333333"><dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency></span></span>

如不想启用网关,则配置 spring.cloud.gateway.enabled=false.

Spring Cloud Gateway is built on Spring Boot 2.x, Spring WebFlux, and Project Reactor.

术语:

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:过滤器

3.工作流程

Clients make requests to Spring Cloud Gateway. If the Gateway Handler Mapping determines that a request matches a route, it is sent to the Gateway Web Handler. This handler runs the request through a filter chain that is specific to the request. The reason the filters are divided by the dotted line is that filters can run logic both before and after the proxy request is sent. All “pre” filter logic is executed. Then the proxy request is made. After the proxy request is made, the “post” filter logic is run.

配置:

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  application:
    name: gateway
  cloud:
    nacos:
      config:
        server-addr: 172.16.102.215:12100
        file-extension: yaml
        namespace: dd229d69-1788-4800-b511-c646bb140dd7
        group: DEFAULT_GROUP
        prefix: gateway
        refresh-enabled: true
    gateway:
      discovery:
        locator:
          enabled: false # 与服务注册与发现组件结合,设置为 true 后;id默认为微服务名称xxx-server;
                          #gatewayapplication有feign自动做负载均衡; 不需要定制化显式配置;已生成默认的id=xservice,uri: lb://xserver , path=/serviceId/**
      routes:
      - id: 1
        uri: http://www.baidu.com/
        predicates:
          - Path=/model/**
        filters:
        - StripPrefix=1 #表示在将请求发送到下游之前从请求中剥离的路径个数。
        - name: RequestRateLimiter #请求数据限流, 名称不能随便写
          args:
            key-resolver: '#{@urlKeyResolver}'
            redis-rate-limiter.replenishRate: 300 #令牌桶每秒填充平均速率
            redis-rate-limiter.burstCapacity: 600 #令牌桶总容量</span></span>

内置的过滤器工厂

这里简单将Spring Cloud Gateway内置的所有过滤器工厂整理成了一张表格,虽然不是很详细,但能作为速览使用。如下:

过滤器工厂作用参数
AddRequestHeader为原始请求添加HeaderHeader的名称及值
AddRequestParameter为原始请求添加请求参数参数名称及值
AddResponseHeader为原始响应添加HeaderHeader的名称及值
DedupeResponseHeader剔除响应头中重复的值需要去重的Header名称及去重策略
Hystrix为路由引入Hystrix的断路器保护HystrixCommand的名称
FallbackHeaders为fallbackUri的请求头中添加具体的异常信息Header的名称
PrefixPath为原始请求路径添加前缀前缀路径
PreserveHostHeader为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host
RequestRateLimiter用于对请求限流,限流算法为令牌桶keyResolver、rateLimiter、statusCode、denyEmptyKey、emptyKeyStatus
RedirectTo将原始请求重定向到指定的URLhttp状态码及重定向的url
RemoveHopByHopHeadersFilter为原始请求删除IETF组织规定的一系列Header默认就会启用,可以通过配置指定仅删除哪些Header
RemoveRequestHeader为原始请求删除某个HeaderHeader名称
RemoveResponseHeader为原始响应删除某个HeaderHeader名称
RewritePath重写原始的请求路径原始路径正则表达式以及重写后路径的正则表达式
RewriteResponseHeader重写原始响应中的某个HeaderHeader名称,值的正则表达式,重写后的值
SaveSession在转发请求之前,强制执行WebSession::save操作
SecureHeaders为原始响应添加一系列起安全作用的响应头无,支持修改这些安全响应头的值
SetPath修改原始的请求路径修改后的路径
SetResponseHeader修改原始响应中某个Header的值Header名称,修改后的值
SetStatus修改原始响应的状态码HTTP 状态码,可以是数字,也可以是字符串
StripPrefix用于截断原始请求的路径使用数字表示要截断的路径的数量
Retry针对不同的响应进行重试retries、statuses、methods、series
RequestSize设置允许接收最大请求包的大小。如果请求包大小超过设置的值,则返回 413 Payload Too Large请求包大小,单位为字节,默认值为5M
ModifyRequestBody在转发请求之前修改原始请求体内容修改后的请求体内容
ModifyResponseBody修改原始响应体的内容修改后的响应体内容
Default为所有路由添加过滤器过滤器工厂名称及值
SetRequestHeader增加请求header
RequestSize请求量

uri 配置方式:

4.1快捷配置

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - Cookie=mycookie,mycookievalue #多个条件使用,</span></span>

4.2 完全扩展的参数

扩展的参数通常会有一个name,一个args ,args 通常是配置过滤器键值对

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - name: Cookie
          args:
            name: mycookie
            regexp: mycookievalue</span></span>

5.Rote Predicate Factories 路由断言

5.1After Rote Predicate 在断言之后

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: after_route
        uri: https://example.org
        predicates:
        - After=2017-01-20T17:42:47.789-07:00[America/Denver]</span></span>

5.2 Before Rote Predicate 在断言之前

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: before_route
        uri: https://example.org
        predicates:
        - Before=2017-01-20T17:42:47.789-07:00[America/Denver]</span></span>

5.3 Between Route 中间

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - 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]</span></span>

The Cookie Route Predicate 使用cookie

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: cookie_route
        uri: https://example.org
        predicates:
        - Cookie=chocolate, ch.p</span></span>

The Header Route Predicate 断言使用header

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: header_route
        uri: https://example.org
        predicates:
        - Header=X-Request-Id, \d+</span></span>

5.6 The Host Route Predicate 断言使用host

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: host_route
        uri: https://example.org
        predicates:
        - Host=**.somehost.org,**.anotherhost.org</span></span>

5.7 The Method Route Predicate

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: method_route
        uri: https://example.org
        predicates:
        - Method=GET,POST</span></span>

5.8. The Path Route Predicate Factory 路径断言

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: path_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment},/blue/{segment}</span></span>

跳转之后的链接为https://example.org/red/{segment}

<span style="background-color:#f8f8f8"><span style="color:#333333">// 获取请求参数
Map<String, String> uriVariables = ServerWebExchangeUtils.getPathPredicateVariables(exchange);
​
String segment = uriVariables.get("segment");</span></span>

5.9. The Query Route Predicate Factory 查询断言

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=green</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">##  请求参数red=gree 时才匹配,会成功转发
spring:
  cloud:
    gateway:
      routes:
      - id: query_route
        uri: https://example.org
        predicates:
        - Query=red, gree</span></span>

5.10. The RemoteAddr Route Predicate Factory 远程路径

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: remoteaddr_route
        uri: https://example.org
        predicates:
        - RemoteAddr=192.168.1.1/24</span></span>

5.11. The Weight Route Predicate Factory 权重

<span style="background-color:#f8f8f8"><span style="color:#333333">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
#This route would forward ~80% of traffic to weighthigh.org and ~20% of traffic to weighlow.org</span></span>

5.11.1. Modifying the Way Remote Addresses Are Resolved

<span style="background-color:#f8f8f8"><span style="color:#333333">RemoteAddressResolver resolver = XForwardedRemoteAddressResolver
    .maxTrustedIndex(1);
​
...
​
.route("direct-route",
    r -> r.remoteAddr("10.1.1.1", "10.10.1.1/24")
        .uri("https://downstream1")
.route("proxied-route",
    r -> r.remoteAddr(resolver, "10.10.1.1", "10.10.1.1/24")
        .uri("https://downstream2")
)</span></span>

6.GatewayFilter Factories 网关过滤

6.1 The AddRequestHeader GatewayFilter Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue</span></span>

header 中添加参数传参

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - AddRequestHeader=X-Request-Red, Blue-{segment}
        # 动态传参</span></span>

6.2 The AddRequestParameter GatewayFilter Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        filters:
        - AddRequestParameter=red, blue
        #通过url 传参,相当于?red=blue</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - AddRequestParameter=foo, bar-{segment}</span></span>

6.3 The AddResponseHeader GatewayFilter Factory 响应头

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue
        #返回结果header
        X-Response-Red →Blue</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - AddResponseHeader=foo, bar-{segment}</span></span>

6.4The DedupeResponseHeader GatewayFilter Factory 过滤重复响应头

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: dedupe_response_header_route
        uri: https://example.org
        filters:
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin, RETAIN_FIRST
        #剔除重复响应头,多个以空格隔开
        RETAIN_FIRST: 默认值,保留第一个值
        RETAIN_LAST: 保留最后一个值
        RETAIN_UNIQUE: 保留所有唯一值,以它们第一次出现的顺序保留</span></span>

6.5 The Hystrix GatewayFilter Factory 熔断

Hystrix:断路器

开启断路器功能,需添加hystrix的相关依赖

<span style="background-color:#f8f8f8"><span style="color:#333333"><dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency></span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: https://example.org
        filters:
        - Hystrix=myCommandName</span></span>

自定义

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/consumingserviceendpoint
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/fallback
        - RewritePath=/consumingserviceendpoint, /backingserviceendpoint</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">@GetMapping("/fallback")
public Object fallback() {
Map<String,Object> result = new HashMap<>(3);
result.put("data",null);
result.put("message","request fallback!!!");
result.put("code",500);
return result;
}</span></span>

也可以直接请求断路器,不影响正常跳转

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - 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
        </span></span>

配置熔断器时间测试该配置不行,暂时不知道原因

<span style="background-color:#f8f8f8"><span style="color:#333333">hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000</span></span>

6.6. Spring Cloud CircuitBreaker GatewayFilter Factory

CircuitBreaker: 短路器

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: circuitbreaker_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/red
        filters:
        - name: CircuitBreaker
          args:
            name: myCircuitBreaker
            fallbackUri: forward:/inCaseOfFailureUseThis
        - RewritePath=/red, /blue
       # RewritePath=/red(?<segment>/?.*), $\{segment} 动态参数</span></span>

- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint

重写路径

/red/123 => /blue/123

java 配置如下

<span style="background-color:#f8f8f8"><span style="color:#333333">@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
            .filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))
                .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
        .build();
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">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</span></span>

6.6.1. Tripping The Circuit Breaker On Status Codes 返回状态

根据返回的状态码,解除短路器

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: circuitbreaker_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/consumingServiceEndpoint
        filters:
        - name: CircuitBreaker
          args:
            name: myCircuitBreaker
            fallbackUri: forward:/inCaseOfFailureUseThis
            statusCodes:
              - 500
              - "NOT_FOUND"</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
    return builder.routes()
        .route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
            .filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))
                .rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
        .build();
}</span></span>

6.7. The FallbackHeaders GatewayFilter Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">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</span></span>
  • executionExceptionTypeHeaderName ("Execution-Exception-Type")

  • executionExceptionMessageHeaderName ("Execution-Exception-Message")

  • rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")

  • rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")

6.8 The MapRequestHeader GatewayFilter Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: map_request_header_route
        uri: https://example.org
        filters:
        - MapRequestHeader=Blue, X-Request-Red</span></span>

在header添加参数,映射,fromHeaderandtoHeader

返回值:

xRequestRed:2222222,12321312 Blue:12321312

6.9 The PrefixPath GatewayFilter Factory 路径前缀

PrefixPath:前缀

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - PrefixPath=/mypath</span></span>

请求hello 转发为 /mypath/hello

6.10 The PreserveHostHeader GatewayFilter Factory

The PreserveHostHeader GatewayFilter factory has no parameters.

为请求添加一个preserveHostHeader=true的属性,路由过滤器会检查该属性以决定是否要发送原始的Host

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: preserve_host_route
        uri: https://example.org
        filters:
        - PreserveHostHeader</span></span>

6.11. The RequestRateLimiter GatewayFilter Factory 请求速率限制

rate:速率

determine :确定

The RequestRateLimiter GatewayFilter factory uses a RateLimiter implementation to determine if the current request is allowed to proceed. If it is not, a status of HTTP 429 - Too Many Requests (by default) is returned.

详细使用流程:

spring cloud gateway 自带了个限流器filter,就是RequestRateLimiter,可以使用令牌桶算法来限流

先说下令牌桶算法,就是:每秒向令牌桶放N个令牌,令牌桶的最大容积是M个,那么如果请求过来了,会从令牌桶中拿出一个令牌,令牌桶还剩M-1个。以此类推,当令牌桶的数量还剩0个的时候,就拒绝接受请求。所以这个情况可以支持突发性的请求情况。就是我一致很小量的请求,但是突然来了一大波请求,令牌桶容积决定了它能接受的最大突发情况。

首先看下spring cloud gateway的配置,注意要用到redis

<span style="background-color:#f8f8f8"><span style="color:#333333">    - id: lb2thorquest
        uri: lb://THORQUEST
        order: 9999
        predicates:
        - Host=10.1.0.75:9001
        filters:
        - name: RequestRateLimiter
          args:
            redis-rate-limiter.replenishRate: 1  # 令牌桶放入的速度
            redis-rate-limiter.burstCapacity: 3  # 令牌桶的容积
            key-resolver: "#{@remoteAddrKeyResolver}" #SPEL表达式去的对应的bean
  redis:
    host: 10.10.2.175
    port: 6379
    database: 5</span></span>

引入redis

<span style="background-color:#f8f8f8"><span style="color:#333333"> <span style="color:#117700"><</span><span style="color:#117700">dependency</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>org.springframework.boot<span style="color:#117700"></</span><span style="color:#117700">groupId</span><span style="color:#117700">></span>
            <span style="color:#117700"><</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>spring-boot-starter-data-redis-reactive<span style="color:#117700"></</span><span style="color:#117700">artifactId</span><span style="color:#117700">></span>
        <span style="color:#117700"></</span><span style="color:#117700">dependency</span><span style="color:#117700">></span></span></span>

这个key resolver会生成一个key,为这个key生成一个令牌桶。如果是客户端ip,那么就是为每个ip生成一个令牌桶。如果是个固定值,就是全局的令牌桶。

<span style="background-color:#f8f8f8"><span style="color:#333333">  <span style="color:#555555">@Bean</span>
    <span style="color:#000000">KeyResolver</span> <span style="color:#0000ff">remoteAddrKeyResolver</span>() {
        <span style="color:#770088">return</span> <span style="color:#000000">exchange</span> <span style="color:#981a1a">-></span> <span style="color:#000000">Mono</span>.<span style="color:#000000">just</span>(<span style="color:#000000">Objects</span>.<span style="color:#000000">requireNonNull</span>(<span style="color:#000000">exchange</span>.<span style="color:#000000">getRequest</span>().<span style="color:#000000">getRemoteAddress</span>()).<span style="color:#000000">getHostName</span>());
    }</span></span>

那么使劲刷新url,出现429 too many request 就表示成功了,

By default, if the KeyResolver does not find a key, requests are denied. You can adjust this behavior by setting the spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true or false) and spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code properties.

The RequestRateLimiter is not configurable with the "shortcut" notation. The following example below is invalid:Example 35. application.properties# INVALID SHORTCUT CONFIGURATION spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}

6.11.1 The Redis RateLimiter

he Redis implementation is based off of work done at Stripe. It requires the use of the spring-boot-starter-data-redis-reactive Spring Boot starter.

要求添加依赖

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis-reactive</artifactId> </dependency>

<span style="background-color:#f8f8f8"><span style="color:#333333">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 #一个请求需要几个令牌,默认是1
            </span></span>

replenishRate=1, requestedTokens=60 and burstCapacity=60 will result in a limit of 1 request/min.

<span style="background-color:#f8f8f8"><span style="color:#333333">@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"  需先定义
            key-resolver: "#{@userKeyResolver}"  需先定义</span></span>

6.12 The RedirectTo GatewayFilter Factory 重定向

The RedirectTo GatewayFilter factory takes two parameters, status and url.

有两个参数 status ,url

The status parameter should be a 300 series redirect HTTP code, such as 301. The url parameter should be a valid URL.

status 参数应该是300系列 重定向 http code,像301 ,url 应该是个有效的url

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - RedirectTo=302, https://acme.org</span></span>

状态码:

已定义范围分类
1XX100-101信息提示
2XX200-206成功
3XX300-305重定向
4XX400-415客户端错误
5XX500-505服务器错误

6.13 The RevoveRequestHeader GatewayFilter Factory

The RemoveRequestHeader GatewayFilter factory takes a name parameter. It is the name of the header to be removed.

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveRequestHeader=X-Request-Foo #移除header  X-Request-Foo</span></span>

6.14 RemoveResponseHeader Gateway Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: https://example.org
        filters:
        - RemoveResponseHeader=X-Response-Foo #移除响应头 X-Response-Foo</span></span>

6.15 The RemoveRequestParamter GatewayFilter Factory

The RemoveRequestParameter GatewayFilter factory takes a name parameter. It is the name of the query parameter to be removed. The following example configures a RemoveRequestParameter GatewayFilter:

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: removerequestparameter_route
        uri: https://example.org
        filters:
        - RemoveRequestParameter=red #移除请求参数 red</span></span>

6.16 The RewritePath GatewayFilter Factory 重写路径

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: rewritepath_route
        uri: https://example.org
        predicates:
        - Path=/red/**
        filters:
        - RewritePath=/red(?<segment>/?.*), $\{segment}</span></span>

重写路径

/red/blue => /blue/red

6.18 RewriteLocationResonseHeader GateWayFilter Factory 重写响应头中 Location 的值

不太懂

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: rewritelocationresponseheader_route
        uri: http://hxmec.com
        filters:
        - RewriteLocationResponseHeader=AS_IN_REQUEST, Location, ,
如上所示,一个请求 POST api.anoyi.com/some/object/name, Response header Location 的值 prod.anoyi.com/v2/some/object/id 将被改为 api.anoyi.com/some/object/id</span></span>

参数 stripVersionMode 可选值如下:

NEVER_STRIP:版本信息不会被剥离,即使原始请求路径不包含版本 AS_IN_REQUEST:仅当原始请求路径不包含任何版本时,才会剥离版本【默认】 ALWAYS_STRIP:即使原始请求路径包含版本,也会剥离版本 参数 hostValue,如果提供,会替换 Response Header Location 值中的 host:port 部分;如果不提供,则会使用 Request 的 Host 作为默认值 参数 protocolRegex,协议会与该值匹配,如果不匹配,过滤器不回做任何操作,默认值 http|https|ftp|ftps

6.18. The RewriteResponseHeader GatewayFilter Factory

RewriteResponseHeader 重写原始响应中的某个Header Header名称,值的正则表达式,重写后的值

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: rewriteresponseheader_route
        uri: https://example.org
        filters:
        - RewriteResponseHeader=X-Response-Red, , password=[^&]+, password=***</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">response.setHeader("X-Response-Red", "/42?user=ford&password=omg!what&flag=true");</span></span>

image-20210825154347623

6.19. The SaveSession GatewayFilter Factory

保存 Session,在向下游服务转发请求之前强制执行 WebSession::save操作

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: save_session
        uri: https://example.org
        predicates:
        - Path=/foo/**
        filters:
        - SaveSession</span></span>

如果将 Spring Security 与 Spring Session 集成,并希望确保安全性详细信息已转发到远程进程,那么这一点至关重要。

6.20. The SecureHeader GatewayFilter Factory unknow

SecureHeaders会向响应添加多个头数据,主要是根据这篇博客的建议:Everything you need to know about HTTP security headers。 会添加下面这些头,括号中是默认值。

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 这些属性是与上面列出要添加的头是对应的,在 SecureHeadersProperties.java 安全头属性类文件中可以看到。 要禁用默认值,设置spring.cloud.gateway.filter.secure-headers.disable属性,值使用逗号分隔符(,)。注意,值必须是安全标头(secure headers)的小写全名。如下所示: spring.cloud.gateway.filter.secure-headers.disable=x-frame-options,strict-transport-security

6.21 The SetPath GatewayFilter Factory 修改路径

SetPath 修改原始的请求路径 修改后的路径

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: setpath_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - SetPath=/{segment}</span></span>

For a request path of /red/blue, this sets the path to /blue before making the downstream request.

6.22 The SetRequestHeader GatewayFilter Factory

有两个参数 name , value

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: setrequestheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - SetRequestHeader=foo, bar-{segment}</span></span>

6.23. The SetResponseHeader GatewayFilter Factory 设置响应头

有两个参数 name ,value

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: setresponseheader_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - SetResponseHeader=foo, bar-{segment}</span></span>

6.24 The SetStatus GatewayFilter Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: setstatusstring_route
        uri: https://example.org
        filters:
        - SetStatus=BAD_REQUEST
      - id: setstatusint_route
        uri: https://example.org
        filters:
        - SetStatus=401</span></span>
<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      set-status:
        original-status-header-name: original-http-status</span></span>

6.25 The StripPrefix GatewayFilter Factory 剥离路径

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: nameRoot
        uri: https://nameservice
        predicates:
        - Path=/name/**
        filters:
        - StripPrefix=2 </span></span>

When a request is made through the gateway to /name/blue/red, the request made to nameservice looks like nameservice/red.

6.26. The Retry GatewayFilter Factory 重试

The Retry GatewayFilter factory supports the following parameters:

  • retries: The number of retries that should be attempted.

  • statuses: The HTTP status codes that should be retried, represented by using org.springframework.http.HttpStatus.

  • methods: The HTTP methods that should be retried, represented by using org.springframework.http.HttpMethod.

  • series: The series of status codes to be retried, represented by using org.springframework.http.HttpStatus.Series.

  • exceptions: A list of thrown exceptions that should be retried.

  • backoff: The configured exponential backoff for the retries. Retries are performed after a backoff interval of firstBackoff * (factor ^ n), where n is the iteration. If maxBackoff is configured, the maximum backoff applied is limited to maxBackoff. If basedOnPreviousValue is true, the backoff is calculated byusing prevBackoff * factor.

The following defaults are configured for Retry filter, if enabled:

  • retries: Three times

  • series: 5XX series

  • methods: GET method

  • exceptions: IOException and TimeoutException

  • backoff: disabled

The following listing configures a Retry GatewayFilter:

<span style="background-color:#f8f8f8"><span style="color:#333333">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
            exceptions: java.lang.RuntimeException   #需写类名,否则转换不了,报错
            backoff:
              firstBackoff: 10ms
              maxBackoff: 50ms
              factor: 2
              basedOnPreviousValue: false</span></span>

6.27. The RequestSize GatewayFilter Factory

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: request_size_route
        uri: http://localhost:8080/upload
        predicates:
        - Path=/upload
        filters:
        - name: RequestSize
          args:
            maxSize: 5000000</span></span>

6.28. The SetRequestHostHeader GatewayFilter Factory

certain 某些

situation : 情况

<span style="background-color:#f8f8f8"><span style="color:#333333">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</span></span>

The SetRequestHostHeader GatewayFilter factory replaces the value of the host header with example.org. 替换host

6.29. Modify a Request Body GatewayFilter Factory 修改请求体

You can use the ModifyRequestBody filter filter to modify the request body before it is sent downstream by the gateway.

This filter can be configured only by using the Java DSL.

The following listing shows how to modify a request body GatewayFilter:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@Bean</span>
<span style="color:#770088">public</span> <span style="color:#000000">RouteLocator</span> <span style="color:#0000ff">routes</span>(<span style="color:#000000">RouteLocatorBuilder</span> <span style="color:#000000">builder</span>) {
    <span style="color:#770088">return</span> <span style="color:#000000">builder</span>.<span style="color:#000000">routes</span>()
        .<span style="color:#000000">route</span>(<span style="color:#aa1111">"rewrite_request_obj"</span>, <span style="color:#000000">r</span> <span style="color:#981a1a">-></span> <span style="color:#000000">r</span>.<span style="color:#000000">host</span>(<span style="color:#aa1111">"*.rewriterequestobj.org"</span>)
            .<span style="color:#000000">filters</span>(<span style="color:#000000">f</span> <span style="color:#981a1a">-></span> <span style="color:#000000">f</span>.<span style="color:#000000">prefixPath</span>(<span style="color:#aa1111">"/httpbin"</span>)
                .<span style="color:#000000">modifyRequestBody</span>(<span style="color:#008855">String</span>.<span style="color:#770088">class</span>, <span style="color:#000000">Hello</span>.<span style="color:#770088">class</span>, <span style="color:#000000">MediaType</span>.<span style="color:#000000">APPLICATION_JSON_VALUE</span>,
                    (<span style="color:#000000">exchange</span>, <span style="color:#000000">s</span>) <span style="color:#981a1a">-></span> <span style="color:#770088">return</span> <span style="color:#000000">Mono</span>.<span style="color:#000000">just</span>(<span style="color:#770088">new</span> <span style="color:#000000">Hello</span>(<span style="color:#000000">s</span>.<span style="color:#000000">toUpperCase</span>())))).<span style="color:#000000">uri</span>(<span style="color:#000000">uri</span>))
        .<span style="color:#000000">build</span>();
}
​
<span style="color:#770088">static</span> <span style="color:#770088">class</span> <span style="color:#0000ff">Hello</span> {
    <span style="color:#008855">String</span> <span style="color:#000000">message</span>;
​
    <span style="color:#770088">public</span> <span style="color:#000000">Hello</span>() { }
​
    <span style="color:#770088">public</span> <span style="color:#000000">Hello</span>(<span style="color:#008855">String</span> <span style="color:#000000">message</span>) {
        <span style="color:#770088">this</span>.<span style="color:#000000">message</span> <span style="color:#981a1a">=</span> <span style="color:#000000">message</span>;
    }
​
    <span style="color:#770088">public</span> <span style="color:#008855">String</span> <span style="color:#000000">getMessage</span>() {
        <span style="color:#770088">return</span> <span style="color:#000000">message</span>;
    }
​
    <span style="color:#770088">public</span> <span style="color:#008855">void</span> <span style="color:#000000">setMessage</span>(<span style="color:#008855">String</span> <span style="color:#000000">message</span>) {
        <span style="color:#770088">this</span>.<span style="color:#000000">message</span> <span style="color:#981a1a">=</span> <span style="color:#000000">message</span>;
    }
}</span></span>
if the request has no body, the RewriteFilter will be passed null. Mono.empty() should be returned to assign a missing body in the request.

6.30. Modify a Response Body GatewayFilter Factory 想改响应体

<span style="background-color:#f8f8f8"><span style="color:#333333">@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();
}</span></span>

6.31. Default Filter 默认过滤

To add a filter and apply it to all routes, you can use spring.cloud.gateway.default-filters. This property takes a list of filters. The following listing defines a set of default filters:

Example 58. application.yml

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      default-filters:
      - AddResponseHeader=X-Response-Default-Red, Default-Blue
      - PrefixPath=/httpbin</span></span>

7. Global Filters 全局过滤

7.1 Combined Global Filter and GatewayFilter Ordering 组合全局过滤器和网关过滤器排序

Combined: 结合

When a request matches a route, the filtering web handler adds all instances of GlobalFilter and all route-specific instances of GatewayFilter to a filter chain. This combined filter chain is sorted by the org.springframework.core.Ordered interface, which you can set by implementing the getOrder() method.

As Spring Cloud Gateway distinguishes between “pre” and “post” phases for filter logic execution (see How it Works), the filter with the highest precedence is the first in the “pre”-phase and the last in the “post”-phase.

<span style="background-color:#f8f8f8"><span style="color:#333333">@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;
    }
}</span></span>

7.2. Foward Routing Filter

The ForwardRoutingFilter looks for a URI in the exchange attribute ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR. If the URL has a forward scheme (such as forward:///localendpoint), it uses the Spring DispatcherHandler to handle the request. The path part of the request URL is overridden with the path in the forward URL. The unmodified original URL is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute.

7.3. The LoadBalancerClient Filter

LoadBalancerClient Filter整合Ribbon实现负载均衡

url 使用服务代替

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**</span></span>

7.4. The ReactiveLoadBalancerClientFilter

The ReactiveLoadBalancerClientFilter looks for a URI in the exchange attribute named ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR. If the URL has a lb scheme (such as lb://myservice), it uses the Spring Cloud ReactorLoadBalancer to resolve the name (myservice in this example) to an actual host and port and replaces the URI in the same attribute. The unmodified original URL is appended to the list in the ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR attribute. The filter also looks in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR attribute to see if it equals lb. If so, the same rules apply. The following listing configures a ReactiveLoadBalancerClientFilter:

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**</span></span>

By default, when a service instance cannot be found by the ReactorLoadBalancer, a 503 is returned. You can configure the gateway to return a 404 by setting spring.cloud.gateway.loadbalancer.use404=true.

The isSecure value of the ServiceInstance returned from the ReactiveLoadBalancerClientFilter overrides the scheme specified in the request made to the Gateway. For example, if the request comes into the Gateway over HTTPS but the ServiceInstance indicates it is not secure, the downstream request is made over HTTP. The opposite situation can also apply. However, if GATEWAY_SCHEME_PREFIX_ATTR is specified for the route in the Gateway configuration, the prefix is stripped and the resulting scheme from the route URL overrides the ServiceInstance configuration.

7.5.The Netty Routing Filter --了解

使用Netty的 HttpClient 转发http、https请求 ----------- 了解

The Netty routing filter runs if the URL located in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute has a http or https scheme. It uses the Netty HttpClient to make the downstream proxy request. The response is put in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute for use in a later filter. (There is also an experimental WebClientHttpRoutingFilter that performs the same function but does not require Netty.)

7.6. The Netty Write Response Filter 将代理响应写回网关的客户端侧--了解

The NettyWriteResponseFilter runs if there is a Netty HttpClientResponse in the ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR exchange attribute. It runs after all other filters have completed and writes the proxy response back to the gateway client response. (There is also an experimental WebClientWriteResponseFilter that performs the same function but does not require Netty.)

7.7. The RouteToRequestUrl Filter --将从request里获取的原始url转换成Gateway进行请求转发时所使用的url

If there is a Route object in the ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR exchange attribute, the RouteToRequestUrlFilter runs. It creates a new URI, based off of the request URI but updated with the URI attribute of the Route object. The new URI is placed in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute`.

If the URI has a scheme prefix, such as lb:ws://serviceid, the lb scheme is stripped from the URI and placed in the ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR for use later in the filter chain.

7.8. The Websocket Routing Filter --- 使用Spring Web Socket将转发 Websocket 请求

  • Websocket 路由过滤器

If the URL located in the ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR exchange attribute has a ws or wss scheme, the websocket routing filter runs. It uses the Spring WebSocket infrastructure to forward the websocket request downstream.

You can load-balance websockets by prefixing the URI with lb, such as lb:ws://serviceid.

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      # SockJS route
      - id: websocket_sockjs_route
        uri: http://localhost:3001
        predicates:
        - Path=/websocket/info/**
      # Normal Websocket route
      - id: websocket_route
        uri: ws://localhost:3001
        predicates:
        - Path=/websocket/**</span></span>

7.9. The Gateway Metrics Filter 监控指标

To enable gateway metrics, add spring-boot-starter-actuator as a project dependency. Then, by default, the gateway metrics filter runs as long as the property spring.cloud.gateway.metrics.enabled is not set to false. This filter adds a timer metric named gateway.requests with the following tags:

  • routeId: The route ID.

  • routeUri: The URI to which the API is routed.

  • outcome: The outcome, as classified by HttpStatus.Series.

  • status: The HTTP status of the request returned to the client.

  • httpStatusCode: The HTTP Status of the request returned to the client.

  • httpMethod: The HTTP method used for the request.

These metrics are then available to be scraped from /actuator/metrics/gateway.requests and can be easily integrated with Prometheus to create a Grafana dashboard.

7.10. Marking An Exchange As Routed

防止重复的路由转发

After the gateway has routed a ServerWebExchange, it marks that exchange as “routed” by adding gatewayAlreadyRouted to the exchange attributes. Once a request has been marked as routed, other routing filters will not route the request again, essentially skipping the filter. There are convenience methods that you can use to mark an exchange as routed or check if an exchange has already been routed.

  • ServerWebExchangeUtils.isAlreadyRouted takes a ServerWebExchange object and checks if it has been “routed”.

  • ServerWebExchangeUtils.setAlreadyRouted takes a ServerWebExchange object and marks it as “routed”.

8. HttpHeadersFilters

8.1 Forwarded Headers Filter

The Forwarded Headers Filter creates a Forwarded header to send to the downstream service. It adds the Host header, scheme and port of the current request to any existing Forwarded header.

8.2. RemoveHopByHop Headers Filter

The RemoveHopByHop Headers Filter removes headers from forwarded requests. The default list of headers that is removed comes from the IETF.

The default removed headers are:

  • Connection

  • Keep-Alive

  • Proxy-Authenticate

  • Proxy-Authorization

  • TE

  • Trailer

  • Transfer-Encoding

  • Upgrade

To change this, set the spring.cloud.gateway.filter.remove-hop-by-hop.headers property to the list of header names to remove.

8.3 XForwarded Headers Filter

The XForwarded Headers Filter creates various a X-Forwarded-* headers to send to the downstream service. It users the Host header, scheme, port and path of the current request to create the various headers.

Creating of individual headers can be controlled by the following boolean properties (defaults to true):

  • spring.cloud.gateway.x-forwarded.for-enabled

  • spring.cloud.gateway.x-forwarded.host-enabled

  • spring.cloud.gateway.x-forwarded.port-enabled

  • spring.cloud.gateway.x-forwarded.proto-enabled

  • spring.cloud.gateway.x-forwarded.prefix-enabled

Appending multiple headers can be controlled by the following boolean properties (defaults to true):

  • spring.cloud.gateway.x-forwarded.for-append

  • spring.cloud.gateway.x-forwarded.host-append

  • spring.cloud.gateway.x-forwarded.port-append

  • spring.cloud.gateway.x-forwarded.proto-append

  • spring.cloud.gateway.x-forwarded.prefix-append

9. TLS and SSL

<span style="background-color:#f8f8f8"><span style="color:#333333">server:
  ssl:
    enabled: true
    key-alias: scg
    key-store-password: scg1234
    key-store: classpath:scg-keystore.p12
    key-store-type: PKCS12</span></span>

设置信任路由证书

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          useInsecureTrustManager: true</span></span>

Using an insecure trust manager is not suitable for production. For a production deployment, you can configure the gateway with a set of known certificates that it can trust with the following configuration:

设置证书

Example 65. application.yml

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#221199">spring</span><span style="color:#555555">:</span>
<span style="color:#221199">  cloud</span><span style="color:#555555">:</span>
<span style="color:#221199">    gateway</span><span style="color:#555555">:</span>
<span style="color:#221199">      httpclient</span><span style="color:#555555">:</span>
<span style="color:#221199">        ssl</span><span style="color:#555555">:</span>
<span style="color:#221199">          trustedX509Certificates</span><span style="color:#555555">:</span>
<span style="color:#555555">          - </span>cert1.pem
<span style="color:#555555">          - </span>cert2.pem</span></span>

如果Spring Cloud Gateway没有提供受信任的证书,则使用默认的信任存储(您可以通过设置javax.net.ssl.trustStore系统属性来覆盖它)。

9.1. TLS Handshake

TLS 相关设置

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      httpclient:
        ssl:
          handshake-timeout-millis: 10000
          close-notify-flush-timeout-millis: 3000
          close-notify-read-timeout-millis: 0</span></span>

10. Configuration 配置

11. Route Metadata Configuration

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      routes:
      - id: route_with_metadata
        uri: https://example.org
        metadata:
          optionName: "OptionValue"
          compositeObject:
            name: "value"
          iAmNumber: 1</span></span>

You could acquire all metadata properties from an exchange, as follows:

<span style="background-color:#f8f8f8"><span style="color:#333333">Route route = exchange.getAttribute(GATEWAY_ROUTE_ATTR);
// get all metadata properties
route.getMetadata();
// get a single metadata property
route.getMetadata(someKey);</span></span>

12. Http Timeouts configration 超时

12.1 Global timeouts

To configure Global http timeouts: connect-timeout must be specified in milliseconds. response-timeout must be specified as a java.time.Duration

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 1000
        response-timeout: 5s</span></span>

12.2 Pre-route timeouts

To configure per-route timeouts: connect-timeout must be specified in milliseconds. response-timeout must be specified in milliseconds.

<span style="background-color:#f8f8f8"><span style="color:#333333">      - id: per_route_timeouts
        uri: https://example.org
        predicates:
          - name: Path
            args:
              pattern: /delay/{timeout}
        metadata:
          response-timeout: 200
          connect-timeout: 200</span></span>

per-route timeouts configuration using Java DSL

<span style="background-color:#f8f8f8"><span style="color:#333333">import static org.springframework.cloud.gateway.support.RouteMetadataUtils.CONNECT_TIMEOUT_ATTR;
import static org.springframework.cloud.gateway.support.RouteMetadataUtils.RESPONSE_TIMEOUT_ATTR;
​
      @Bean
      public RouteLocator customRouteLocator(RouteLocatorBuilder routeBuilder){
         return routeBuilder.routes()
               .route("test1", r -> {
                  return r.host("*.somehost.org").and().path("/somepath")
                        .filters(f -> f.addRequestHeader("header1", "header-value-1"))
                        .uri("http://someuri")
                        .metadata(RESPONSE_TIMEOUT_ATTR, 200)
                        .metadata(CONNECT_TIMEOUT_ATTR, 200);
               })
               .build();
      }</span></span>

12.3. Fluent Java Routes API

<span style="background-color:#f8f8f8"><span style="color:#333333">@Bean
public RouteLocator customRouteLocator(RouteLocatorBuilder builder, ThrottleGatewayFilterFactory throttle) {
    return builder.routes()
            .route(r -> r.host("**.abc.org").and().path("/image/png")
                .filters(f ->
                        f.addResponseHeader("X-TestHeader", "foobar"))
                .uri("http://httpbin.org:80")
            )
            .route(r -> r.path("/image/webp")
                .filters(f ->
                        f.addResponseHeader("X-AnotherHeader", "baz"))
                .uri("http://httpbin.org:80")
                .metadata("key", "value")
            )
            .route(r -> r.order(-1)
                .host("**.throttle.org").and().path("/get")
                .filters(f -> f.filter(throttle.apply(1,
                        1,
                        10,
                        TimeUnit.SECONDS)))
                .uri("http://httpbin.org:80")
                .metadata("key", "value")
            )
            .build();
}</span></span>

This style also allows for more custom predicate assertions. The predicates defined by RouteDefinitionLocator beans are combined using logical and. By using the fluent Java API, you can use the and(), or(), and negate() operators on the Predicate class.

12.4. The DiscoveryClient Route Definition Locator

You can configure the gateway to create routes based on services registered with a DiscoveryClient compatible service registry.

To enable this, set spring.cloud.gateway.discovery.locator.enabled=true and make sure a DiscoveryClient implementation (such as Netflix Eureka, Consul, or Zookeeper) is on the classpath and enabled.

使用服务注册中心 ,文档没说清楚,查询别的博客,说是配置后,id默认为服务名称

测试id故意写错,uri正常服务写法,可以正常访问

12.4.1 Configuring Predicates and Filters For DiscoveryClient Routes

The default predicate is a path predicate defined with the pattern /serviceId/**, where serviceId is the ID of the service from the DiscoveryClient.

默认使用服务id配置路径

The default filter is a rewrite path filter with the regex /serviceId/(?<remaining>.*) and the replacement /${remaining}. This strips the service ID from the path before the request is sent downstream.

默认过滤器会重写路径,过滤掉服务id

If you want to customize the predicates or filters used by the DiscoveryClient routes, set spring.cloud.gateway.discovery.locator.predicates[x] and spring.cloud.gateway.discovery.locator.filters[y]. When doing so, you need to make sure to include the default predicate and filter shown earlier, if you want to retain that functionality. The following example shows what this looks like:

Example 71. application.properties

<span style="background-color:#f8f8f8"><span style="color:#333333">spring.cloud.gateway.discovery.locator.predicates[0].name: Path
spring.cloud.gateway.discovery.locator.predicates[0].args[pattern]: "'/'+serviceId+'/**'"
spring.cloud.gateway.discovery.locator.predicates[1].name: Host
spring.cloud.gateway.discovery.locator.predicates[1].args[pattern]: "'**.foo.com'"
spring.cloud.gateway.discovery.locator.filters[0].name: Hystrix
spring.cloud.gateway.discovery.locator.filters[0].args[name]: serviceId
spring.cloud.gateway.discovery.locator.filters[1].name: RewritePath
spring.cloud.gateway.discovery.locator.filters[1].args[regexp]: "'/' + serviceId + '/(?<remaining>.*)'"
spring.cloud.gateway.discovery.locator.filters[1].args[replacement]: "'/${remaining}'"</span></span>

13. Reactor Netty Access Logs

To enable Reactor Netty access logs, set -Dreactor.netty.http.server.accessLogEnabled=true.

配置netty log参数

Example 72. logback.xml

<span style="background-color:#f8f8f8"><span style="color:#333333"> <appender name="accessLog" class="ch.qos.logback.core.FileAppender">
        <file>access_log.log</file>
        <encoder>
            <pattern>%msg%n</pattern>
        </encoder>
    </appender>
    <appender name="async" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="accessLog" />
    </appender>
​
    <logger name="reactor.netty.http.server.AccessLog" level="INFO" additivity="false">
        <appender-ref ref="async"/>
    </logger></span></span>

14.CORS Configuration 跨域

<span style="background-color:#f8f8f8"><span style="color:#333333">spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "https://docs.spring.io"
            allowedMethods:
            - GET</span></span>

To provide the same CORS configuration to requests that are not handled by some gateway route predicate, set the spring.cloud.gateway.globalcors.add-to-simple-url-handler-mapping property to true. This is useful when you try to support CORS preflight requests and your route predicate does not evalute to true because the HTTP method is options.

15. Actuator API-----执行器

The /gateway actuator endpoint lets you monitor and interact with a Spring Cloud Gateway application. To be remotely accessible, the endpoint has to be enabled and exposed over HTTP or JMX in the application properties. The following listing shows how to do so:

/gateway执行器端点允许您监视Spring云网关应用程序并与之交互。要实现远程访问,必须在应用程序属性中通过HTTP或JMX启用并公开端点。下面的清单展示了如何做到这一点:

<span style="background-color:#f8f8f8"><span style="color:#333333">management.endpoint.gateway.enabled=true # default value
management.endpoints.web.exposure.include=gateway</span></span>

启动监控接口,需配置以上参数,还需添加依赖(请求404,找了半天,才发现是缺依赖,文档太坑了)

<span style="background-color:#f8f8f8"><span style="color:#333333"><dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency></span></span>

15.1 Verbose Actuator Format 详细格式

Verbose:详细的

A new, more verbose format has been added to Spring Cloud Gateway. It adds more detail to each route, letting you view the predicates and filters associated with each route along with any configuration that is available. The following example configures /actuator/gateway/routes:

Spring Cloud Gateway中添加了一种新的、更详细的格式。它为每个路由添加了更多的细节,允许您查看与每个路由关联的谓词和过滤器以及可用的任何配置。配置/致动器/gateway/routes的示例如下:

<span style="background-color:#f8f8f8"><span style="color:#333333">[
  {
    "predicate": "(Hosts: [**.addrequestheader.org] && Paths: [/headers], match trailing slash: true)",
    "route_id": "add_request_header_test",
    "filters": [
      "[[AddResponseHeader X-Response-Default-Foo = 'Default-Bar'], order = 1]",
      "[[AddRequestHeader X-Request-Foo = 'Bar'], order = 1]",
      "[[PrefixPath prefix = '/httpbin'], order = 2]"
    ],
    "uri": "lb://testservice",
    "order": 0
  }
]</span></span>

This feature is enabled by default. To disable it, set the following property:

Example 75. application.properties

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#0000ff">spring.cloud.gateway.actuator.verbose.enabled</span>=<span style="color:#009900">false</span></span></span>

动态配置路由使用

动态配置路由博客:https://lidong1665.blog.csdn.net/article/details/100933635

15.2. Retrieving Route Filters

This section details how to retrieve route filters, including:

15.2.1 Global Filters

To retrieve the global filters applied to all routes, make a GET request to /actuator/gateway/globalfilters. The resulting response is similar to the following:

<span style="background-color:#f8f8f8"><span style="color:#333333">{
  "org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@77856cc5": 10100,
  "org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@4f6fd101": 10000,
  "org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@32d22650": -1,
  "org.springframework.cloud.gateway.filter.ForwardRoutingFilter@106459d9": 2147483647,
  "org.springframework.cloud.gateway.filter.NettyRoutingFilter@1fbd5e0": 2147483647,
  "org.springframework.cloud.gateway.filter.ForwardPathFilter@33a71d23": 0,
  "org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@135064ea": 2147483637,
  "org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@23c05889": 2147483646
}</span></span>

15.2.2 Route Filter

To retrieve the GatewayFilter factories applied to routes, make a GET request to /actuator/gateway/routefilters. The resulting response is similar to the following:

<span style="background-color:#f8f8f8"><span style="color:#333333">{
  "[AddRequestHeaderGatewayFilterFactory@570ed9c configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null,
  "[SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]": null,
  "[SaveSessionGatewayFilterFactory@4449b273 configClass = Object]": null
}</span></span>

The response contains the details of the GatewayFilter factories applied to any particular route. For each factory there is a string representation of the corresponding object (for example, [SecureHeadersGatewayFilterFactory@fceab5d configClass = Object]). Note that the null value is due to an incomplete implementation of the endpoint controller, because it tries to set the order of the object in the filter chain, which does not apply to a GatewayFilter factory object.

15.3. Refreshing the Route Cache

To clear the routes cache, make a POST request to /actuator/gateway/refresh. The request returns a 200 without a response body.

post请求,返回空实体

15.4. Retrieving the Routes Defined in the Gateway

To retrieve the routes defined in the gateway, make a GET request to /actuator/gateway/routes. The resulting response is similar to the following:

检索路由

GET /actuator/gateway/routes

<span style="background-color:#f8f8f8"><span style="color:#333333">[{
  "route_id": "first_route",
  "route_object": {
    "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@1e9d7e7d",
    "filters": [
      "OrderedGatewayFilter{delegate=org.springframework.cloud.gateway.filter.factory.PreserveHostHeaderGatewayFilterFactory$$Lambda$436/674480275@6631ef72, order=0}"
    ]
  },
  "order": 0
},
{
  "route_id": "second_route",
  "route_object": {
    "predicate": "org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory$$Lambda$432/1736826640@cd8d298",
    "filters": []
  },
  "order": 0
}]</span></span>

The response contains the details of all the routes defined in the gateway. The following table describes the structure of each element (each is a route) of the response:

PathTypeDescription
route_idStringThe route ID.
route_object.predicateObjectThe route predicate.
route_object.filtersArrayThe GatewayFilter factories applied to the route.
orderNumberThe route order.

15.5. Retreving Information about a Particular Route--检索特定的路由信息

To retrieve information about a single route, make a GET request to /actuator/gateway/routes/{id} (for example, /actuator/gateway/routes/first_route). The resulting response is similar to the following:

GET /actuator/gateway/routes/first_route

<span style="background-color:#f8f8f8"><span style="color:#333333">{
  "id": "first_route",
  "predicates": [{
    "name": "Path",
    "args": {"_genkey_0":"/first"}
  }],
  "filters": [],
  "uri": "https://www.uri-destination.org",
  "order": 0
}]</span></span>

The following table describes the structure of the response:

PathTypeDescription
idStringThe route ID.
predicatesArrayThe collection of route predicates. Each item defines the name and the arguments of a given predicate.
filtersArrayThe collection of filters applied to the route.
uriStringThe destination URI of the route.
orderNumberThe route order.

15.6. Creating and Deleting a Particular Route---创建和删除一个特定的路由

To create a route, make a POST request to /gateway/routes/{id_route_to_create} with a JSON body that specifies the fields of the route (see Retrieving Information about a Particular Route).

To delete a route, make a DELETE request to /gateway/routes/{id_route_to_delete}.

15.7. Recap: The List of All endpoints ----概述:所有端点的列表 (所有api)

The folloiwng table below summarizes the Spring Cloud Gateway actuator endpoints (note that each endpoint has /actuator/gateway as the base-path):

IDHTTP MethodDescription
globalfiltersGETDisplays the list of global filters applied to the routes.
routefiltersGETDisplays the list of GatewayFilter factories applied to a particular route.
refreshPOSTClears the routes cache.
routesGETDisplays the list of routes defined in the gateway.
routes/{id}GETDisplays information about a particular route.
routes/{id}POSTAdds a new route to the gateway.
routes/{id}DELETERemoves an existing route from the gateway.

16. Troublesshooting 常见问题

16.1 Log Levels 日志级别

he following loggers may contain valuable troubleshooting information at the DEBUG and TRACE levels:

  • org.springframework.cloud.gateway

  • org.springframework.http.server.reactive

  • org.springframework.web.reactive

  • org.springframework.boot.autoconfigure.web

  • reactor.netty

  • redisratelimiter

16.2. Wiretap 监听

The Reactor Netty HttpClient and HttpServer can have wiretap enabled. When combined with setting the reactor.netty log level to DEBUG or TRACE, it enables the logging of information, such as headers and bodies sent and received across the wire. To enable wiretap, set spring.cloud.gateway.httpserver.wiretap=true or spring.cloud.gateway.httpclient.wiretap=true for the HttpServer and HttpClient, respectively.

翻译:反应器Netty ' HttpClient '和' HttpServer '可以启用窃听。当结合将' reactor.netty '日志级别设置为' DEBUG '或' TRACE '时,它允许记录信息,如通过网络发送和接收的头部和正文。要启用监听功能,请设置“spring.cloud.gateway.httpserver”。窃听= true”或“spring.cloud.gateway.httpclient。wiretap=true ',分别为' HttpServer '和' HttpClient '。

17.Developer Guide--开发者指南

自定义组件指南

17.1. Writing Custeom Route Predicate Factories --- 编写自定义断言

In order to write a Route Predicate you will need to implement RoutePredicateFactory. There is an abstract class called AbstractRoutePredicateFactory which you can extend.

<span style="background-color:#f8f8f8"><span style="color:#333333">public class MyRoutePredicateFactory extends AbstractRoutePredicateFactory<HeaderRoutePredicateFactory.Config> {
​
    public MyRoutePredicateFactory() {
        super(Config.class);
    }
​
    @Override
    public Predicate<ServerWebExchange> apply(Config config) {
        // grab configuration from Config object
        return exchange -> {
            //grab the request
            ServerHttpRequest request = exchange.getRequest();
            //take information from the request to see if it
            //matches configuration.
            return matches(config, request);
        };
    }
​
    public static class Config {
        //Put the configuration properties for your filter here
    }
​
}</span></span>

17.2. Writing Custom GatewayFilter Factories ---编写自定义网关过滤

To write a GatewayFilter, you must implement GatewayFilterFactory. You can extend an abstract class called AbstractGatewayFilterFactory. The following examples show how to do so:

Example 76. PreGatewayFilterFactory.java

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">PreGatewayFilterFactory</span> <span style="color:#770088">extends</span> <span style="color:#000000">AbstractGatewayFilterFactory</span><span style="color:#981a1a"><</span><span style="color:#000000">PreGatewayFilterFactory</span>.<span style="color:#000000">Config</span><span style="color:#981a1a">></span> {
​
    <span style="color:#770088">public</span> <span style="color:#000000">PreGatewayFilterFactory</span>() {
        <span style="color:#770088">super</span>(<span style="color:#000000">Config</span>.<span style="color:#770088">class</span>);
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#000000">GatewayFilter</span> <span style="color:#000000">apply</span>(<span style="color:#000000">Config</span> <span style="color:#000000">config</span>) {
        <span style="color:#aa5500">// grab configuration from Config object</span>
        <span style="color:#770088">return</span> (<span style="color:#000000">exchange</span>, <span style="color:#000000">chain</span>) <span style="color:#981a1a">-></span> {
            <span style="color:#aa5500">//If you want to build a "pre" filter you need to manipulate the</span>
            <span style="color:#aa5500">//request before calling chain.filter</span>
            <span style="color:#000000">ServerHttpRequest</span>.<span style="color:#000000">Builder</span> <span style="color:#000000">builder</span> <span style="color:#981a1a">=</span> <span style="color:#000000">exchange</span>.<span style="color:#000000">getRequest</span>().<span style="color:#000000">mutate</span>();
            <span style="color:#aa5500">//use builder to manipulate the request</span>
            <span style="color:#770088">return</span> <span style="color:#000000">chain</span>.<span style="color:#000000">filter</span>(<span style="color:#000000">exchange</span>.<span style="color:#000000">mutate</span>().<span style="color:#000000">request</span>(<span style="color:#000000">builder</span>.<span style="color:#000000">build</span>()).<span style="color:#000000">build</span>());
        };
    }
​
    <span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#770088">class</span> <span style="color:#0000ff">Config</span> {
        <span style="color:#aa5500">//Put the configuration properties for your filter here</span>
    }
​
}</span></span>

PostGatewayFilterFactory.java

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">PostGatewayFilterFactory</span> <span style="color:#770088">extends</span> <span style="color:#000000">AbstractGatewayFilterFactory</span><span style="color:#981a1a"><</span><span style="color:#000000">PostGatewayFilterFactory</span>.<span style="color:#000000">Config</span><span style="color:#981a1a">></span> {
​
    <span style="color:#770088">public</span> <span style="color:#000000">PostGatewayFilterFactory</span>() {
        <span style="color:#770088">super</span>(<span style="color:#000000">Config</span>.<span style="color:#770088">class</span>);
    }
​
    <span style="color:#555555">@Override</span>
    <span style="color:#770088">public</span> <span style="color:#000000">GatewayFilter</span> <span style="color:#000000">apply</span>(<span style="color:#000000">Config</span> <span style="color:#000000">config</span>) {
        <span style="color:#aa5500">// grab configuration from Config object</span>
        <span style="color:#770088">return</span> (<span style="color:#000000">exchange</span>, <span style="color:#000000">chain</span>) <span style="color:#981a1a">-></span> {
            <span style="color:#770088">return</span> <span style="color:#000000">chain</span>.<span style="color:#000000">filter</span>(<span style="color:#000000">exchange</span>).<span style="color:#000000">then</span>(<span style="color:#000000">Mono</span>.<span style="color:#000000">fromRunnable</span>(() <span style="color:#981a1a">-></span> {
                <span style="color:#000000">ServerHttpResponse</span> <span style="color:#000000">response</span> <span style="color:#981a1a">=</span> <span style="color:#000000">exchange</span>.<span style="color:#000000">getResponse</span>();
                <span style="color:#aa5500">//Manipulate the response in some way</span>
            }));
        };
    }
​
    <span style="color:#770088">public</span> <span style="color:#770088">static</span> <span style="color:#770088">class</span> <span style="color:#0000ff">Config</span> {
        <span style="color:#aa5500">//Put the configuration properties for your filter here</span>
    }
​
}
​</span></span>

17.2.1. Naming Custom Filters And References In Configuration

在配置中命名自定义过滤器和引用

Custom filters class names should end in GatewayFilterFactory.

自定义过滤器类名应该以 GatewayFilterFactory 结尾

For example, to reference a filter named Something in configuration files, the filter must be in a class named SomethingGatewayFilterFactory.

例如,要在配置文件中引用一个名为' Something '的过滤器,该过滤器必须在一个名为' SomethingGatewayFilterFactory '的类中。

It is possible to create a gateway filter named without theGatewayFilterFactorysuffix, such asclass AnotherThing. This filter could be referenced asAnotherThingin configuration files. This is **not** a supported naming convention and this syntax may be removed in future releases. Please update the filter name to be compliant.

17.3 Writing Custom Global Filters 编写自定义全局过滤器

To write a custom global filter, you must implement GlobalFilter interface. This applies the filter to all requests.

The following examples show how to set up global pre and post filters, respectively:

<span style="background-color:#f8f8f8"><span style="color:#333333">@Bean
public GlobalFilter customGlobalFilter() {
    return (exchange, chain) -> exchange.getPrincipal()
        .map(Principal::getName)
        .defaultIfEmpty("Default User")
        .map(userName -> {
          //adds header to proxied request
          exchange.getRequest().mutate().header("CUSTOM-REQUEST-HEADER", userName).build();
          return exchange;
        })
        .flatMap(chain::filter);
}
​
@Bean
public GlobalFilter customGlobalPostFilter() {
    return (exchange, chain) -> chain.filter(exchange)
        .then(Mono.just(exchange))
        .map(serverWebExchange -> {
          //adds header to response
          serverWebExchange.getResponse().getHeaders().set("CUSTOM-RESPONSE-HEADER",
              HttpStatus.OK.equals(serverWebExchange.getResponse().getStatusCode()) ? "It worked": "It did not work");
          return serverWebExchange;
        })
        .then();
}</span></span>

18. Building a Simple Gateway by Using Spring MVC or Webflux

The following describes an alternative style gateway. None of the prior documentation applies to what follows.

Spring Cloud Gateway provides a utility object called ProxyExchange. You can use it inside a regular Spring web handler as a method parameter. It supports basic downstream HTTP exchanges through methods that mirror the HTTP verbs. With MVC, it also supports forwarding to a local handler through the forward() method. To use the ProxyExchange, include the right module in your classpath (either spring-cloud-gateway-mvc or spring-cloud-gateway-webflux).

The following MVC example proxies a request to /test downstream to a remote server:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@RestController</span>
<span style="color:#555555">@SpringBootApplication</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">GatewaySampleApplication</span> {
​
    <span style="color:#555555">@Value</span>(<span style="color:#aa1111">"${remote.home}"</span>)
    <span style="color:#770088">private</span> <span style="color:#000000">URI</span> <span style="color:#000000">home</span>;
​
    <span style="color:#555555">@GetMapping</span>(<span style="color:#aa1111">"/test"</span>)
    <span style="color:#770088">public</span> <span style="color:#000000">ResponseEntity</span><span style="color:#981a1a"><?></span> <span style="color:#000000">proxy</span>(<span style="color:#000000">ProxyExchange</span><span style="color:#981a1a"><</span><span style="color:#008855">byte</span>[]<span style="color:#981a1a">></span> <span style="color:#000000">proxy</span>) <span style="color:#770088">throws</span> <span style="color:#000000">Exception</span> {
        <span style="color:#770088">return</span> <span style="color:#000000">proxy</span>.<span style="color:#000000">uri</span>(<span style="color:#000000">home</span>.<span style="color:#000000">toString</span>() <span style="color:#981a1a">+</span> <span style="color:#aa1111">"/image/png"</span>).<span style="color:#000000">get</span>();
    }
​
}</span></span>

The following example does the same thing with Webflux:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@RestController</span>
<span style="color:#555555">@SpringBootApplication</span>
<span style="color:#770088">public</span> <span style="color:#770088">class</span> <span style="color:#0000ff">GatewaySampleApplication</span> {
​
    <span style="color:#555555">@Value</span>(<span style="color:#aa1111">"${remote.home}"</span>)
    <span style="color:#770088">private</span> <span style="color:#000000">URI</span> <span style="color:#000000">home</span>;
​
    <span style="color:#555555">@GetMapping</span>(<span style="color:#aa1111">"/test"</span>)
    <span style="color:#770088">public</span> <span style="color:#000000">Mono</span><span style="color:#981a1a"><</span><span style="color:#000000">ResponseEntity</span><span style="color:#981a1a"><?>></span> <span style="color:#000000">proxy</span>(<span style="color:#000000">ProxyExchange</span><span style="color:#981a1a"><</span><span style="color:#008855">byte</span>[]<span style="color:#981a1a">></span> <span style="color:#000000">proxy</span>) <span style="color:#770088">throws</span> <span style="color:#000000">Exception</span> {
        <span style="color:#770088">return</span> <span style="color:#000000">proxy</span>.<span style="color:#000000">uri</span>(<span style="color:#000000">home</span>.<span style="color:#000000">toString</span>() <span style="color:#981a1a">+</span> <span style="color:#aa1111">"/image/png"</span>).<span style="color:#000000">get</span>();
    }
​
}</span></span>

Convenience methods on the ProxyExchange enable the handler method to discover and enhance the URI path of the incoming request. For example, you might want to extract the trailing elements of a path to pass them downstream:

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#555555">@GetMapping</span>(<span style="color:#aa1111">"/proxy/path/**"</span>)
<span style="color:#770088">public</span> <span style="color:#000000">ResponseEntity</span><span style="color:#981a1a"><?></span> <span style="color:#0000ff">proxyPath</span>(<span style="color:#000000">ProxyExchange</span><span style="color:#981a1a"><</span><span style="color:#008855">byte</span>[]<span style="color:#981a1a">></span> <span style="color:#000000">proxy</span>) <span style="color:#770088">throws</span> <span style="color:#000000">Exception</span> {
  <span style="color:#008855">String</span> <span style="color:#000000">path</span> <span style="color:#981a1a">=</span> <span style="color:#000000">proxy</span>.<span style="color:#000000">path</span>(<span style="color:#aa1111">"/proxy/path/"</span>);
  <span style="color:#770088">return</span> <span style="color:#000000">proxy</span>.<span style="color:#000000">uri</span>(<span style="color:#000000">home</span>.<span style="color:#000000">toString</span>() <span style="color:#981a1a">+</span> <span style="color:#aa1111">"/foos/"</span> <span style="color:#981a1a">+</span> <span style="color:#000000">path</span>).<span style="color:#000000">get</span>();
}</span></span>

All the features of Spring MVC and Webflux are available to gateway handler methods. As a result, you can inject request headers and query parameters, for instance, and you can constrain the incoming requests with declarations in the mapping annotation. See the documentation for @RequestMapping in Spring MVC for more details of those features.

You can add headers to the downstream response by using the header() methods on ProxyExchange.

You can also manipulate response headers (and anything else you like in the response) by adding a mapper to the get() method (and other methods). The mapper is a Function that takes the incoming ResponseEntity and converts it to an outgoing one.

First-class support is provided for “sensitive” headers (by default, cookie and authorization), which are not passed downstream, and for “proxy” (x-forwarded-*) headers.

19. Configuration properties

Appendix A: Common application properties

Various properties can be specified inside your application.properties file, inside your application.yml file, or as command line switches. This appendix provides a list of common Spring Cloud Gateway properties and references to the underlying classes that consume them.

Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list. Also, you can define your own properties.

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐