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

配置(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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM