Spring Cloud Gateway内置GatewayFilter工厂类 (一)

路由过滤器允许以某种方式对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

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

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

可以看到,配置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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,670评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,928评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,926评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,238评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,112评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,138评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,545评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,232评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,496评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,596评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,369评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,226评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,600评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,906评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,185评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,516评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,721评论 2 335

推荐阅读更多精彩内容