Spring Cloud Gateway使用说明(2)-- 路由filter(上)

6. 路由filter

过滤器允许以某种方式修改传入的HTTP请求或返回的HTTP响应。过滤器的作用域是某些特定路由。Spring Cloud Gateway包括许多内置的 Filter工厂。

 

 有关如何使用以下任何过滤器的更详细示例,请查看 unit tests.

6.1 添加请求Header

为请求添加header, 采用一对名称和值作为参数

Example 13. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        filters:
        - AddRequestHeader=X-Request-red, blue

"X-Request-red:blue"会被添加到路由的请求header中。

AddRequestHeader 可以和URI变量一起用,如:

Example 14. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: https://example.org
        predicates:
        - Path=/red/{segment}
        filters:
        - AddRequestHeader=X-Request-Red, Blue-{segment}

6.2 添加请求参数

为请求添加参数,采用一对名称和值作为参数

Example 15. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        filters:
        - AddRequestParameter=red, blue

对于所有匹配的请求,这将向下游请求添加red=blue查询字符串

AddRequestParameter也可以和path或host断言 的URI变量结合使用,如:

Example 16. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_parameter_route
        uri: https://example.org
        predicates:
        - Host: {segment}.myhost.org
        filters:
        - AddRequestParameter=foo, bar-{segment}

6.3 添加响应Header

为响应添加header,采用一对名称和值作为参数

Example 17. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: add_response_header_route
        uri: https://example.org
        filters:
        - AddResponseHeader=X-Response-Red, Blue

对于所有匹配的请求,这会将x-response-Red:Blue头添加到下游响应的header中.

同样也可以和URI变量一起使用

6.4.  删除重复header 

删除响应头重复值

如果在代码和代理(如nginx)中都有添加header的配置时,有可能会重复添加,引发异常。

DedupeResponseHeader GatewayFilter Factory采用名称参数和可选策略参数。name可以包含标题名称列表,空格分隔。

Example 19. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: dedupe_response_header_route
        uri: https://example.org
        filters:
        - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin

在网关CORS逻辑和下游添加它们的情况下,这将删除Access-Control-Allow-Credentials和Access-Control-Allow-Origin响应头的重复值。

DedupeResponseHeader过滤器还接受可选的策略参数。接受的值为RETAIN_FIRST(默认值),RETAIN_LAST和RETAIN_UNIQUE。

6.5 Hystrix 过滤器

hystrix网关断路器

Hystrix 是Netflix开源的断路器组件。Hystrix GatewayFilter允许你向网关路由引入断路器,保护你的服务不受级联故障的影响,并允许你在下游故障时提供fallback响应。

注意
Hystrix已经进入维护期,我们建议你使用基于Resilience4J的Spring Cloud CircuitBreaker Gateway Filter ,
在以后的版本中Hystrix会被移除。

Hystrix 是Netflix开源的断路器组件。Hystrix GatewayFilter允许你向网关路由引入断路器,保护你的服务不受级联故障的影响,并允许你在下游故障时提供fallback响应。

要在项目中启用Hystrix网关过滤器,需要添加对 spring-cloud-starter-netflix-hystrix的依赖 Spring Cloud Netflix.

Hystrix GatewayFilter Factory 需要一个name参数,即HystrixCommand的名称。

Example 20. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: https://example.org
        filters:
        - Hystrix=myCommandName

这将剩余的过滤器包装在命令名为“myCommandName”的HystrixCommand中。

hystrix过滤器还可以接受可选的fallbackUri 参数。目前,仅支持forward: 预设的URI,如果调用fallback,则请求将转发到与URI匹配的控制器。

Example 21. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: hystrix_route
        uri: lb://backing-service:8088
        predicates:
        - Path=/consumingserviceendpoint
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd
            fallbackUri: forward:/incaseoffailureusethis
        - RewritePath=/consumingserviceendpoint, /backingserviceendpoint

当调用hystrix fallback时,这将转发到/incaseoffailureusethis uri。注意,这个示例还演示了(可选)通过目标URI上的'lb`前缀,使用Spring Cloud Netflix Ribbon 客户端负载均衡。

主要场景是使用fallbackUri 到网关应用程序中的内部控制器或处理程序。但是,也可以将请求重新路由到外部应用程序中的控制器或处理程序,如:

Example 22. application.yml

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

在本例中,gateway应用程序中没有 fallback 实现,但是另一个应用程序中有一个接口实现,注册为“http://localhost:9994”。

在将请求转发到fallback的情况下,Hystrix Gateway过滤还支持直接抛出Throwable 。它被作为ServerWebExchangeUtils.HYSTRIX_EXECUTION_EXCEPTION_ATTR属性添加到ServerWebExchange中,可以在处理网关应用程序中的fallback时使用。

对于外部控制器/处理程序方案,可以添加带有异常详细信息的header。可以在 FallbackHeaders GatewayFilter Factory section中找到有关它的更多信息。

hystrix配置参数(如 timeouts)可以使用全局默认值配置,也可以使用Hystrix wiki中所述属性进行配置

要为上面的示例路由设置5秒超时,将使用以下配置:

Example 23. application.yml

hystrix.command.fallbackcmd.execution.isolation.thread.timeoutInMilliseconds: 5000

6.6. Spring Cloud CircuitBreaker

网关断路器

Spring Cloud CircuitBreaker 支持使用 Hystrix 和 Resilience4J 两个库实现,但由于Hystrix已经进入维护模式, 我们推荐使用Resilience4J。

启用Spring Cloud CircuitBreaker filter 首先引入对应的依赖:

spring-cloud-starter-circuitbreaker-reactor-resilience4j

spring-cloud-starter-netflix-hystrix

然后添加配置:

Example 24. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: circuitbreaker_route
        uri: https://example.org
        filters:
        - CircuitBreaker=myCircuitBreaker

详细配置项可以查看对应的说明文档:

The Spring Cloud CircuitBreaker filter 还可以使用 fallbackUri 参数,但 目前只能和 forward: 搭配使用; fallback被触发时,请用会被转发到对应的URI,配置如下:

Example 25. application.yml

mple 25. application.yml

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

以下java代码的方式进行配置可以达到同样的效果:

@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();
}

 

例子中fallback同时会把请求转发到 /inCaseofFailureUseThis, RewritePath配置会把地址由 /consumingServiceEndpoint 重写为 /backingServiceEndpoint 。 同时,例子中也使用了 lb 前缀实现负载均衡。

上面的例子是把请求转发到应用内的controller或handler, 但是 fallbackUri 也支持把请求转发到应用外的地址,如:

Example 27. application.yml

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

这个例子把请求转发到 地址为 localhost:9994 的另一个应用

在fallback转发的请求中, 可以通过 ServerWebExchange 中的 ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 属性获取到对应的 Throwable , 更多的异常信息见下一节。

6.7. FallbackHeaders

FallbackHeaders允许在转发到外部应用程序中的FallbackUri的请求的header中添加Hystrix或 Spring Cloud CircuitBreake异常详细信息,如下所示:

Example 28. application.yml

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

在本例中,在发生异常后,请求将被circuit breaker转发到 localhost:9994应用程序中的 fallback终端或程序。异常类型、消息和(如果有)根cause exception类型和消息,将由FallbackHeaders filter添加到该请求的头中。

下面列出参数值及其默认值,可以在配置中覆盖headers的名称:

  • executionExceptionTypeHeaderName ("Execution-Exception-Type")
  • executionExceptionMessageHeaderName ("Execution-Exception-Message")
  • rootCauseExceptionTypeHeaderName ("Root-Cause-Exception-Type")
  • rootCauseExceptionMessageHeaderName ("Root-Cause-Exception-Message")


更多信息查看:Hystrix GatewayFilter Factory sectionSpring Cloud CircuitBreaker Factory section.

6.8.  修改请求header名称

可以修改header的名称,需要 fromHeader(原header) 和 toHeader(新header)两个参数。如果原header不存在,则不会有任何效果。如果新header已经存在,则会被覆盖。

Example 29. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: map_request_header_route
        uri: https://example.org
        filters:
        - MapRequestHeader=Blue, X-Request-Red

header Blue 名称会被修改为X-Request-Red

6.9.  添加url前缀

可以给请求地址添加前缀。如:

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - PrefixPath=/mypath

前缀/mypath会添加到所有匹配到的请求地址中。因此 /hello 会发送到 /mypath/hello.

6.10.  Host header保护

保存host header。

该filter没有参数。设置了该Filter后,GatewayFilter将不使用由HTTP客户端设置的host header ,而是发送原始host header 。

Example 31. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: preserve_host_route
        uri: https://example.org
        filters:
        - PreserveHostHeader

6.11. 限流

用户限流器,默认根据登录账号限制请求速率。

RequestRateLimiter使用RateLimiter的实现决定是否允许继续执行当前请求。如果不允许继续执行,则返回HTTP 429 - Too Many Requests (默认情况下)。

这个过滤器可以配置一个可选的keyResolver 参数和rate limiter参数(见下文)。

keyResolverKeyResolver 接口的实现类.在配置中,按名称使用SpEL引用bean。#{@myKeyResolver} 是引用名为'myKeyResolver'的bean的SpEL表达式。

SpEL用法可以查看文章 SpEL 在注解中的使用
 

Example 32. KeyResolver.java

public interface KeyResolver {
    Mono<String> resolve(ServerWebExchange exchange);
}

KeyResolver接口允许使用可插拔策略来派生限制请求的key。在未来的里程碑版本中,将有一些KeyResolver实现。

KeyResolver的默认实现是PrincipalNameKeyResolver,它从ServerWebExchange检索Principal并调用Principal.getName()

默认情况下,如果KeyResolver 没有获取到key,请求将被拒绝。此行为可以使用 spring.cloud.gateway.filter.request-rate-limiter.deny-empty-key (true or false) 和 spring.cloud.gateway.filter.request-rate-limiter.empty-key-status-code属性进行调整。

 

注意

无法通过"简化模式" 配置RequestRateLimiter。以下示例无效

# 不合法的简化模式配置
spring.cloud.gateway.routes[0].filters[0]=RequestRateLimiter=2, 2, #{@userkeyresolver}

6.11.1. Redis RateLimiter

Redis的实现基于 Stripe。它需要使用 spring-boot-starter-data-redis-reactive Spring Boot starter。

使用的算法是 令牌桶算法 , 点击查看。

redis-rate-limiter.replenishRate是你允许用户每秒执行多少请求,而不丢弃任何请求。这是令牌桶的填充速率。

redis-rate-limiter.burstCapacity是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以保存的令牌数。将此值设置为零将阻止所有请求。

redis-rate-limiter.requestedTokens 是每个请求消耗多少个令牌,默认是1.

稳定速率是通过在replenishRate(补充令牌速度) 和 burstCapacity(令牌桶容量)中设置相同的值来实现的。可通过设置burstCapacity高于replenishRate来允许临时突发流浪。在这种情况下,限流器需要在两次突发之间留出一段时间(根据replenishRate),因为连续两次突发将导致请求丢失 (HTTP 429 - Too Many Requests).。

要限制每秒一个请求,可以将replenishRate设置为目标请求数,requestedTokens设置目标的时间秒数,burstCapacity为replenishRate * requestedTokens。如:设置replenishRate=1, requestedTokens=60burstCapacity=60,就是限制每分钟1个请求。

Example 34. application.yml

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

java KeyResolver配置:
Example 35. Config.java

@Bean
KeyResolver userKeyResolver() {
    return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
}

这定义了每个用户10个请求的限制。允许20个突发,但下一秒只有10个请求可用。KeyResolver是一个简单的获取user请求参数的例子(注意:不建议用于生产)。

限流器也可以自定义为实现RateLimiter接口的 bean。在配置中,按名称使用SpEL引用bean。#{@myRateLimiter}是引用名为'myRateLimiter'的bean的SpEL表达式。下面的例子中的KeyResolver是前面定义的。

Example 36. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: requestratelimiter_route
        uri: https://example.org
        filters:
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@myRateLimiter}"
            key-resolver: "#{@userKeyResolver}"

6.12 重定向

该过滤器有一个 status 和一个 url参数。status是300类重定向HTTP代码,如301。该URL应为有效的URL,这将是 Location header的值。


Example 37. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: prefixpath_route
        uri: https://example.org
        filters:
        - RedirectTo=302, https://acme.org

这将发送一个302状态码和一个Location:http://acme.org header来执行重定向。

如果是重定向到相对地址,应该使用 no://op 作为uri值。

spring:
  cloud:
    gateway:
      routes:
      - id: jwt_rate_limiting
        predicates:
          - Path=/login/oauth2/code/login-client
        filters:
          - RedirectTo=302, /login/oauth2/code/login-client
          - name: RequestRateLimiter
            args:
              redis-rate-limiter.replenishRate: 2
              redis-rate-limiter.burstCapacity: 2
        uri: no://op

6.13 删除请求header

指定要删除的header名称即可

Example 38. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removerequestheader_route
        uri: https://example.org
        filters:
        - RemoveRequestHeader=X-Request-Foo

header X-Request-Foo会被移除,然后下发。

6.14 删除响应header

RemoveResponseHeader 指定要删除的header名称,对应的header会被删除。

Example 39. application.yml

spring:
  cloud:
    gateway:
      routes:
      - id: removeresponseheader_route
        uri: https://example.org
        filters:
        - RemoveResponseHeader=X-Response-Foo

返回给客户端前,header X-Response-Foo会被删除。

对于一些敏感的header,你可能会希望对所有的路由进行一次性配置,可以通过spring.cloud.gateway.default-filters实现:

spring:
  cloud:
    gateway:
      default-filters:
      - RemoveResponseHeader=X-Response-Foo
      - AddRequestHeader=X-Request-Name, Value
      - AddRequestParameter=name, value

Spring Cloud Gateway 2.2.3 官方使用说明(1)--路由

Spring Cloud Gateway 2.2.3 官方使用说明(2)-- 路由filter(上)

Spring Cloud Gateway 2.2.3 官方使用说明(2)-- 路由filter(下)

Spring Cloud Gateway 2.2.3 官方使用说明(3)-- Global filter

Spring Cloud Gateway 2.2.3 官方使用说明(4)-- HttpHeader Filters

Spring Cloud Gateway 2.2.3 使用说明(5)-- TLS 和 SSL

Spring Cloud Gateway 2.2.3 使用说明(6)-- 其它配置

Spring Cloud Gateway 2.2.3 使用说明(7)-- actuator

Spring Cloud Gateway 2.2.3 使用说明(8)-- 开发指导

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值