路由過濾器允許以某種方式對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