1、FallbackHeaders GatewayFilter

FallbackHeaders允许在触发熔断转发到外部应用程序中的fallbackUri的请求的标头中添加Spring Cloud CircuitBreaker执行异常详细信息。例如:

spring:
  cloud:
    gateway:
      enabled: true
      routes:
        - id: Goods-Server  # 路由 id,唯一标识
          uri: lb://producer
          predicates:
            #  - Path=/**  # 断言,路由匹配条件,匹配 /product 开头的所有 api
              - Path=/producer/{segment}
          filters:
              - StripPrefix=1
              - AddRequestHeader=X-Request-red, Blue-{segment}
              - AddRequestParameter=red, bar-{segment}
              - DedupeResponseHeader=Access-Control-Allow-Credentials Access-Control-Allow-Origin
              - name: CircuitBreaker
                args:
                    name: myCircuitBreaker
                    fallbackUri: forward:/myfallback
                    statusCodes:
                      - 500
                      - "NOT_FOUND"
        -   id: ingredients-fallback
            uri: http://localhost:8002/
            predicates:
              - Path=/myfallback
            filters:
              - name: FallbackHeaders
                args:
                  rootCauseExceptionMessageHeaderName: Test-Header

8002是Producer服务的端口。触发熔断时会将请求转发到Producer的/myfallback。先注释gatewayServer里面的Fallback Controller,确保降级回调到Producer的/myfallback.

 

修改Producer服务:

@RequestMapping("/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
    System.out.println(request.getHeader("x-request-red"));
    System.out.println(request.getParameter("red"));
    int i = 10 / 0;
    return "hello," + name + "," + port;
}

确保调用服务引发异常。

 
在Producer模块增加服务降级回调:

@RestController
public class FallbackController {
    private String dateStr(){
        return new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date());
    }

    /**
     * 返回字符串类型
     * @return
     */
    @GetMapping("/myfallback")
    public String helloStr(HttpServletRequest request) {
        String s= request.getHeader("Test-Header");
        System.out.println("producer:"+s);
        return "producer myfallback, " + dateStr();
    }
}

访问http://localhost:8500/producer/hello,查看Producer控制台,发现:

 

springgateway支持SSE吗_springgateway支持SSE吗


 

如果将FallbackController移到gatewayServer模块,则服务降级回调/myfallback获取不到请求头。

 
还可以通过设置以下参数的值(以默认值显示)来覆盖配置中标头的名称:

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

2、MapRequestHeader GatewayFilter

MapRequestHeader GatewayFilter采用fromHeader和toHeader参数。它创建一个新的命名标头(toHeader),并从传入的http请求中的现有命名标头(fromHeader)中提取值。如果输入标头不存在,则过滤器没有影响。如果新的命名标头已经存在,则其值将使用新值进行扩充。例如:

spring:
  cloud:
    gateway:
      enabled: true
      routes:
        - id: Goods-Server  # 路由 id,唯一标识
          uri: lb://producer
          predicates:
            #  - Path=/**  # 断言,路由匹配条件,匹配 /product 开头的所有 api
              - Path=/producer/{segment}
          filters:
              - StripPrefix=1
              - MapRequestHeader=X-Request-Red, Blue

 

Producer服务的Controller:

@RequestMapping("/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
    System.out.println(request.getHeader("X-Request-Red"));
    System.out.println(request.getHeader("blue"));
    return "hello," + name + "," + port;
}

 

用Postman调用http://localhost:8500/producer/hello:

 

springgateway支持SSE吗_Server_02


 查看Producer控制台:

 

springgateway支持SSE吗_唯一标识_03


 

3、PrefixPath GatewayFilter

PrefixPath GatewayFilter将在匹配的请求前面加上前缀。例如:

spring:
  cloud:
    gateway:
      enabled: true
      routes:
        - id: Goods-Server  # 路由 id,唯一标识
          uri: lb://producer
          predicates:
            #  - Path=/**  # 断言,路由匹配条件,匹配 /product 开头的所有 api
              - Path=/producer/{segment}
          filters:
              - StripPrefix=1
              - PrefixPath=/mypath

比如请求路径是/producer/hello,StripPrefix会移除/producer,PrefixPath会加前缀,所以请求路径是/mypath/hello。访问http://localhost:8500/producer/hello报404。Producer服务的请求路径从:

@RequestMapping("/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
    return "hello," + name + "," + port;
}

修改为:

@RequestMapping("/mypath/hello")
public String hello(String name, HttpServletRequest request, HttpServletResponse response) {
    return "hello," + name + "," + port;
}

访问http://localhost:8500/producer/hello,成功。

4、PreserveHostHeader GatewayFilter

PreserveHostHeader GatewayFilter没有参数。此筛选器设置一个请求属性,路由过滤器检查该属性以确定是否应发送原始主机标头,而不是HTTP客户端确定的主机标头。

spring:
  cloud:
    gateway:
      enabled: true
      routes:
        - id: Goods-Server  # 路由 id,唯一标识
          uri: lb://producer
          predicates:
            #  - Path=/**  # 断言,路由匹配条件,匹配 /product 开头的所有 api
              - Path=/producer/{segment}
          filters:
              - StripPrefix=1
              - PreserveHostHeader

5、RequestRateLimiter GatewayFilter

RequestRateLimiter GatewayFilter是限速过滤器。如果被限速会返回HTTP 429 - Too Many Requests。使用Redis来限流。所使用的算法是令牌桶算法。

spring:
  cloud:
    gateway:
      enabled: true
      routes:
        - id: Goods-Server  # 路由 id,唯一标识
          uri: lb://producer
          predicates:
            #  - Path=/**  # 断言,路由匹配条件,匹配 /product 开头的所有 api
              - Path=/producer/{segment}
          filters:
              - StripPrefix=1
              - name: RequestRateLimiter
                args:
                  redis-rate-limiter.replenishRate: 20
                  redis-rate-limiter.burstCapacity: 20
                  redis-rate-limiter.requestedTokens: 1
                  key-resolver: "#{@keyResolver}"
  redis:
    host: localhost
    port: 6379

replenishRate是希望用户在不丢弃任何请求的情况下每秒可以执行的请求数。这是填充令牌桶的速率。
burstCapacity是允许用户在一秒钟内执行的最大请求数。这是令牌桶可以容纳的令牌数量。将此值设置为零将阻止所有请求。
requestedTokens是一个请求花费的令牌数。这是针对每个请求从存储桶中获取的令牌数量,默认为1。
KeyResolver接口允许可插入策略用于限制请求的密钥。#{@keyResolver}里面的keyResolver是Bean的名字。

 

在GatewayServer添加依赖并配置:

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

@Configuration
public class MyConfig {

    @Bean("keyResolver")
    public KeyResolver pathKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
    }
}

 

使用jmeter来测试限流:

添加线程组:

 

springgateway支持SSE吗_spring_04


 

设置线程数,循环次数:

 

springgateway支持SSE吗_springgateway支持SSE吗_05


 添加http请求:

 

springgateway支持SSE吗_spring_06


 配置ip,端口,url等:

 

springgateway支持SSE吗_springgateway支持SSE吗_07


 添加汇总报告:

 

springgateway支持SSE吗_Server_08


 点击执行后查看汇总报告:

 

springgateway支持SSE吗_唯一标识_09