路由过滤器允许以某种方式对Http的请求(request)和响应(response)进行修改。对于特定的路由可以配置相应的路由过滤器。Spring Cloud Gateway中也内置了一些GatewayFilter工厂类。

注意,更多路由过滤器的详细使用,可以参考单元测试:https://github.com/spring-cloud/spring-cloud-gateway/tree/master/spring-cloud-gateway-core/src/test/java/org/springframework/cloud/gateway/filter/factory

5.1 AddRequestHeaderGatewayFilter Factory

       AddRequestHeader过滤器工厂的实现类是AddRequestHeaderGatewayFilterFactory,它使用两个参数,一个是name,一个是value。在application.yml中的配置如下所示:

spring:
  cloud:
    gateway:
      routes:
      - id: add_request_header_route
        uri: http://www.xinyues.com
        filters:
        - AddRequestHeader=X-Request-Foo, Bar

配置(1)

这个过滤器将会在下行的请求包头中添加键值对,也可以配合路由断言一起使用,给所有断言匹配的下行请求包头中添加此键值对。为了方便测试,在源码项目中使用了另外一种路由方式:根据服务名路由。如下面配置所示:

spring:
  cloud:
    gateway:
      routes:
       - id: app-a-route     # 根据服务名路由
        uri: lb://app-a   #配置服务id
        predicates:
        - name: Path
          args:
            pattern: /app-a/** # 匹配的路径
        filters:
        - name: RewritePath
          args:
            regexp: /app-a/(?<remaining>.*)
            replacement: /${remaining}
        - name: AddRequestHeader
          args:
            name: X-Request-Foo
            value: Bar

配置(2)

可以看到,配置1与配置2中的filters的配置方式不一样,这是因为配置1只有一个过滤器,而配置2有多个过滤器,如果有多个过滤器,必须按对象定义的格式配置,如果只有一个过滤器可以使用配置1的方式,简化配置。

       这时,启动源码(https://gitee.com/wgslucky/SpringCloud)中的如果请求的spring-cloud-gateway项目和spring-cloud-app-a项目,在浏览器输入请求地址:http://localhost:8080/app-a/app/index,可以看到在spring-cloud-app-a的控制台输了从包头中获取的X-Request-Foo的值Bar。

5.2 AddRequestParameter GatewayFilter Factory

    AddRequestParameter的过滤器工厂的实现类是AddRequestParameterGatewayFilterFactory,它有两个参数,一个是name,一个是value,如下面的配置:

spring:
  cloud:
    gateway:
      routes:
       - id: app-a-route     # 根据服务名路由
        uri: lb://app-a   #配置服务id
        predicates:
        - name: Path
          args:
            pattern: /app-a/** # 匹配的路径
        filters:
        - name: RewritePath
          args:
            regexp: /app-a/(?<remaining>.*)
            replacement: /${remaining}
        - name: AddRequestHeader
          args:
            name: X-Request-Foo
        value: Bar
        - name: AddRequestParameter
          args: 
            name: foo
            value: bar

这个过滤器,可以给所有匹配的路径添加字符串类型的查询参数。

    这时,启动源码中的如果请求的spring-cloud-gateway项目和spring-cloud-app-a项目,在浏览器输入请求地址:http://localhost:8080/app-a/app/add-request-parameter,可以看到日志输出了过滤器中添加的参数

5.3 AddResponseHeader GatewayFilter Factory

    AddResponseHeader过滤器工厂的实现类是AddResponseHeaderGatewayFilterFactory,它有两个参数,一个是name,一个是value,而且都不能为空,在application.yml中的配置如下所示:

spring:
  cloud:
    gateway:
      routes:
       - id: app-a-route     # 根据服务名路由
        uri: lb://app-a   #配置服务id
        predicates:
        - name: Path
          args:
            pattern: /app-a/** # 匹配的路径
        filters:
        - name: RewritePath
          args:
            regexp: /app-a/(?<remaining>.*)
            replacement: /${remaining}
        - name: AddRequestHeader
          args:
            name: X-Request-Foo
        value: Bar
        - name: AddRequestParameter
          args: 
            name: foo
        value: bar
        - name: AddResponseHeader
          args:
            name: foo
            value: bar2

这时,启动源码中的如果请求的spring-cloud-gateway项目和spring-cloud-app-a项目,在浏览器输入请求地址:http://localhost:8080/app-a/app/add-request-parameter,在谷歌浏览器中按F12,刷新请求,可以看到响应的Header里面包括了过滤器添加的值。

5.4 Hystrix GatewayFilter Factory

       Hystrix过滤器工厂的实现类是HystrixGatewayFilterFactory。Hystrix是Netflix的一个库,它实现了circuit breaker pattern。使用Hystrix过滤器,可以向网关引入熔断器,保护网关后面的服务不会因为大流量而失去服务能力。当出现大流量处理不过来的时候,可以向使用Hystrix过滤器提供一个失败的响应,当下行失败事件产生时,就会给客户端直接返回失败响应信息。

       为了使用Hystrix GatewayFilters,需要在项目中添加Hystrix的库依赖,如下面所示:

    <dependency>
       <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>

Hystrix GatewayFilters需要一个name参数,它配置的就是HystrixCommand的名字。在application.yml中配置如下所示:

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

这里fitlers中配置的就是一个名字为myCommandName的HystrixCommand。Hystrix Filters也可以配置一个fallbackUri参数,但是目前,只支持请求的forward:跳转。如果发生了失败,这个请求将会自动跳转到配置的controller中匹配到fallbackUri中。如下面配置所示:

spring:
  cloud:
    gateway:
      routes:
       - id: app-a-route     # 根据服务名路由
        uri: lb://app-a   #配置服务id
        predicates:
        - name: Path
          args:
            pattern: /app-a/** # 匹配的路径
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd   #熔断的名字,可以随便命名
            fallbackUri: forward:/fallback   # 如果触发了熔断,自动跳转到这个URI里面,在任务一个controller里面有这个URI即可。

当Hystrix的fallback被触发时,请求会自动转发到/fallback的URI里面,此URI在Spring Cloud Gateway项目中的定义如下面代码所示:

@RestController
@RequestMapping("/")
public class FallbackController {
    //添加一个Controller方法,用于接收Hystrix失败时的fallback跳转。
    @RequestMapping(value = "/fallback")
    @ResponseStatus
    public Mono<Map<String, Object>> fallback(ServerWebExchange exchange, Throwable throwable) {
        Map<String, Object> result = new HashMap<>(8);
        ServerHttpRequest request = exchange.getRequest();
        result.put("path", request.getPath().pathWithinApplication().value());
        result.put("method", request.getMethodValue());
        if (null != throwable.getCause()) {
            result.put("message", throwable.getCause().getMessage());
        } else {
            result.put("message", throwable.getMessage());
        }
        return Mono.just(result);
    }
}

从上面的案例中可以看到,fallbackUri跳转的是Spring Cloud Gateway项目内部的controller或handler,但是有时候也需要跳转到其它的服务中的controller或handler里面。如下面配置所示:

spring:
  cloud:
    gateway:
      routes:
       - id: app-a-route     # 根据服务名路由
        uri: lb://app-a   #配置服务id
        predicates:
        - name: Path
          args:
            pattern: /app-a/** # 匹配的路径
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd   #熔断的名字,可以随便命名
            fallbackUri: forward:/fallback   # 如果触发了熔断,自动跳转到这个URI里面,在任务一个controller里面有这个URI即可。
      - id: app-a-route-fallback
        uri: lb://app-b
        predicates:
        - Path=/fallback
        filters:
        - name: RewritePath
          args:
            regexp: /fallback
            replacement: /app/fallback

在源码中,如果启动动网关服务和spring-clouad-app-b服务,不启动spring-cloud-app-a服务,在浏览器中请求:http://localhost:8080/app-a/app/add-request-parameter,可以看到返回的内容是spring-cloud-app-b中AppController的fallback方法中返回的内容。

       Hystrix的参数可以配置成全局默认值,也可以基本应用程序的属性配置,详细的可以参考Hystrix Wiki : https://github.com/Netflix/Hystrix/wiki/Configuration,比如配置上面例子中的fallbackcmd的超时时间为15秒,如下配置所示:

hystrix: 
  command:
    fallbackcmd:
        execution: 
            isolation:
              thread:
                timeoutInMilliseconds: 15000

5.5 FallbackHeaders GatewayFilter Factory

       FallbackHeaders过滤器工厂的实现类是FallbackHeadersGatewayFilterFactory。当Hytrix触发fallback调用并且fallbackUri跳转的是另外一个服务的地址时,这个过滤器可以向跳转请求的Header中添加失败的详细信息。如下面的配置所示:

spring:
  cloud:
    gateway:
      routes:
       - id: app-a-route     # 根据服务名路由
        uri: lb://app-a   #配置服务id
        predicates:
        - name: Path
          args:
            pattern: /app-a/** # 匹配的路径
        filters:
        - name: Hystrix
          args:
            name: fallbackcmd   #熔断的名字,可以随便命名
            fallbackUri: forward:/fallback   # 如果触发了熔断,自动跳转到这个URI里面,在任务一个controller里面有这个URI即可。
      - id: app-a-route-fallback
        uri: lb://app-b
        predicates:
        - Path=/fallback
        filters:
        - name: RewritePath
          args:
            regexp: /fallback
            replacement: /app/fallback
        - name: FallbackHeaders
          args:
            executionExceptionTypeHeaderName: Test-Header

在源码中,启动网关和spring-cloud-app-b服务,然后请求http://localhost:8080/app-a/app/add-request-parameter可以看到网页输了所有header中的信息,其它就是上面定义的test-header(只不过全部小写了)。如果想获取更多详细的信息,可以在args中配置更多的字段,这些字段名在FallbackHeadersGatewayFilterFactory的Config类里面,如下面代码所示:

        private String executionExceptionTypeHeaderName = EXECUTION_EXCEPTION_TYPE;
        private String executionExceptionMessageHeaderName = EXECUTION_EXCEPTION_MESSAGE;
        private String rootCauseExceptionTypeHeaderName = ROOT_CAUSE_EXCEPTION_TYPE;
        private String rootCauseExceptionMessageHeaderName = ROOT_CAUSE_EXCEPTION_MESSAGE;

源码地址:https://gitee.com/wgslucky/SpringCloud    QQ交流群:677464431

转载于:https://www.cnblogs.com/wgslucky/p/11422433.html

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐