一、概述
Spring Cloud Gateway根據作用範圍劃分為:GatewayFilter和GlobalFilter
1、filter的作用和生命周期
由filter工作流程點,可以知道filter有着非常重要的作用,在“pre”類型的過濾器可以做參數校驗、權限校驗、流量監控、日志輸出、協定轉換等,在“post”類型的過濾器中可以做響應内容、響應頭的修改,日志的輸出,流量監控等
作用
網關過濾器用于攔截并鍊式處理Web請求,可以實作橫切與應用無關的需求,比如:鑒權、限流、日志輸出等
生命周期
Spring Cloud Gateway同zuul類似,有“pre”和“post”兩種方式的filter。用戶端的請求先經過“pre”類型的filter,然後将請求轉發到具體的業務服務,比如上圖中的user-service,收到業務服務的響應之後,再經過“post”類型的filter處理,最後傳回響應到用戶端。filter從作用範圍可分為另外兩種,一種是針對于單個路由的gateway filter,它在配置檔案中的寫法同predict類似;另外一種是針對于所有路由的global gateway filer
二、網關過濾器 GatewayFilter
過濾器允許以某種方式修改傳入的HTTP請求或傳出的HTTP響應。過濾器可以限定作用在某些特定請求路徑上。可以實作橫切與應用無關的需求,比如:安全、通路逾時的設定等。修改傳入的HTTP請求或傳出HTTP響應。Spring Cloud Gateway 包含許多内置的網關過濾器工廠,一共22個。包括頭部過濾器、路徑過濾器、Hystrix過濾器和重寫請求URL的過濾器,還有參數和狀态碼等其他類型的過濾器。根據過濾器工程的用途來劃分,可以分為以下幾種:Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter 和 Hystrix。 Spring Cloud Gateway包含許多内置的GatewayFilter工廠。
GatewayFilter工廠同上一篇介紹的Predicate工廠類似,都是在配置檔案application.yml中配置,遵循了約定大于配置的思想,隻需要在配置檔案配置GatewayFilter Factory的名稱,而不需要寫全部的類名,比如AddRequestHeaderGatewayFilterFactory隻需要在配置檔案中寫AddRequestHeader,而不是全部類名。在配置檔案中配置的GatewayFilter Factory最終都會相應的過濾器工廠類處理。
1、AddRequestHeader
描述
1、用于向下遊服務 添加 請求頭,
2、支援 uri variables
參數
1、name:向下遊服務傳遞請求頭的 key
2、value:向下遊服務傳遞請求頭的 value
示例
1、方式一、添加一個固定的請求頭
spring:
cloud:
nacos:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- AddRequestHeader=x-token,xxxxx
表示會向下遊服務傳遞一個 x-token 的請求頭,值是 xxxxx
2、配合 uri variables 添加動态請求頭
spring:
cloud:
gateway:
routes:
- id: product-provider-02
uri: lb://product-provider
predicates:
- Path=/product/findOne/{productId}
filters:
- AddRequestHeader=x-token,xxxxx-{productId}
表示會向下遊服務傳遞一個 x-token 的請求頭,值是 xxxxx-比對上的productId的值
2、AddRequestParameter
描述
用于向下遊服務 添加一個請求參數
參數
name:添加的參數 key
value:添加的參數 value,可以支援 Path或Host 中的 uri variables
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- AddRequestParameter=username,zhangsan
向下遊服務增加一個 username = zhangsan 的請求參數
3、AddResponseHeader
描述
向下遊的響應中增加一個 響應頭。
參數
1、name:添加的響應頭的 key
2、value:添加的響應頭的 value,可以支援 Path或Host 中的 uri variables
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- AddResponseHeader=encryption,false
向下遊服務響應增加一個 encryption = false 的響應頭
4、DedupeResponseHeader
描述
移除重複的請求頭
參數
1、name:需要移除的重複的響應頭,多個以 空格 分隔
2、strategy:重複時,移除的政策,預設是RETAIN_FIRST,即保留第一個頭
- RETAIN_FIRST:保留第一個值
- RETAIN_LAST:保留最後一個值
- RETAIN_UNIQUE:保留所有的不重複的值
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- DedupeResponseHeader=x-token Access-Control-Allow-Credentials Access-Control-Allow-Origin,RETAIN_FIRST
移除上方指定的重複的響應頭,并且保留第一個出現的。
5、MapRequestHeader
描述
将 fromHeader 參數的值 追加到 toHeader 參數中。
- fromHeader 在 header 中不存在,那麼沒有什麼影響。
- fromHeader 存在
- toHeader 存在,那麼往配置中 toHeader 對應的 header 中追加 fromHeader對應的值
- toHeader 不存在,那麼往 header 中增加一個header ,key: 配置中的toHeader的值,value: fromHeader 在header中的值
參數
1、fromHeader:從請求參數中擷取header的值
2、toHeader:向header中設定一個 header, key是toheader的值,value 是 fromHeader的值
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- MapRequestHeader=from-header,x-token
即會向 request 中增加一個 key 為 x-token 的header ,值為 header 中 from-header 對應的值。(存在多種情況,參考描述)
6、Prefix
描述
為比對到的路由,在轉發到下遊服務時,增加一個字首prefix
參數
1、prefix:需要增加的路徑字首
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/findOne
filters:
- PrefixPath=/product
通路 http://網關ip:port/findOne ⇒ 轉發到下遊服務位址 http://product-provider/product/findOne 增加了一個字首。
7、PreserveHostHeader
描述
它表示在Spring Cloud Gateway轉發請求的時候,保持用戶端的Host資訊不變,然後将它傳遞到下遊伺服器中。
參數
沒有參數
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- PreserveHostHeader
8、RemoveRequestHeader
描述
移除請求頭中的參數
參數
1、name:需要移除的請求頭
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- RemoveRequestHeader=x-token
9、RemoveResponseHeader
描述
移除響應頭
參數
1、name:需要移除的響應頭
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- RemoveResponseHeader=x-token
9、RemoveRequestParameter
描述
移除請求參數,往下遊服務傳遞時,此參數就沒有來
參數
1、name:需要移除的請求參數
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- RemoveRequestParameter=password
10、RewritePath
描述
根據正規表達式,執行路徑重寫
參數
1、regexp:比對的正規表達式
2、replacement:需要替換成的字元串
注意:
1、在yml配置中 $ 需要寫成 $\
2、路徑替換規則是: path.replaceAll(regexp,replacement)
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/admin/product/findOne
filters:
- RewritePath=/admin(?<segment>/?.*), $\{segment} # 當通路/admin/product/findOne 将會替換成 /product/findOne
頁面上通路 /admin/product/findOne ⇒ 到達下遊服務的路徑是 /product/findOne
11、StripPrefix
描述
移除路徑字首,比如通路: /admin/aa/bb/cc 實際的下遊伺服器位址是 /bb/cc 則可以使用這個實作
參數
1、parts:請求的路徑按照/分隔後,需要跳過的部分,從1開始。
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/admin/product/findOne
filters:
- StripPrefix=1 # 當通路/admin/product/findOne 将會替換成 /product/findOne
頁面上通路 /admin/product/findOne ⇒ 到達下遊服務的路徑是 /product/findOne
12、RequestSize
描述
配置請求體的大小,當請求體過大時,将會傳回 413 Payload Too Large。
參數
1、maxSize:請求體的大小
示例
spring:
cloud:
gateway:
routes:
- id: product-provider-01
uri: lb://product-provider
predicates:
- Path=/product/findOne
filters:
- name: RequestSize
args:
maxSize: 1B
此處需要通過 filters[index].args.maxSize 配置,否則不生效。
13、ModifyRequestBody
描述
修改傳遞到下遊服務 RequestBody 的值,比如我們所有的經過網關的服務,到達下遊服務時,都需要将 使用者目前的使用者名和資料權限傳遞下去,此時就可以使用這個。
需求:
修改原始服務的參數,增加username和roles參數傳遞到下遊服務。
路由配置,隻可通過 Java 代碼來配置
@Configuration
public class RouteConfig {
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("product-provider", predicateSpec -> predicateSpec.path("/product/modifyRequestBody")
.filters(gatewayFilterSpec -> gatewayFilterSpec.modifyRequestBody(String.class, Map.class, MediaType.APPLICATION_JSON_VALUE, (exchange, s) -> {
Map<String, Object> params = new HashMap<>(16);
params.put("old", s);
params.put("username", "v_huan");
params.put("roles", "ROLE_ADMIN");
return Mono.just(params);
})).uri("lb://product-provider")).build();
}
}
三、全局過濾器
全局過濾器不需要在配置檔案中配置,作用在所有的路由上,最終通過 GatewayFilterAdapter 包裝成 GatewayFilterChain 可識别的過濾器,它是請求業務以及路由的 URI 轉換為真實業務服務請求位址的核心過濾器,不需要配置系統初始化時加載,并作用在每個路由上。
當某個請求被路由比對時,那麼所有的全局過濾器(GlobalFilter)和路由比對到的 GatewayFilter會組合成一個過濾器鍊,排序規則是通過 Spring 的 Ordered 來排序。
GlobalFilter有pre和post2個執行階段,優先級越高 pre 階段執行越早, post階段執行越遲。
編寫一個全局過濾器需要實作 GlobalFilter 接口
下面這些是Gateway内置的全局過濾器,已經在所有路由生效
Spring Cloud Gateway根據作用範圍劃分為GatewayFilter和GlobalFilter,二者差別如下:
- GatewayFilter : 需要通過spring.cloud.routes.filters 配置在具體路由下,隻作用在目前路由上或通過spring.cloud.default-filters配置在全局,作用在所有路由上
- GlobalFilter : 全局過濾器,不需要在配置檔案中配置,作用在所有的路由上,最終通過GatewayFilterAdapter包裝成GatewayFilterChain可識别的過濾器,它為請求業務以及路由的URI轉換為真實業務服務的請求位址的核心過濾器,不需要配置,系統初始化時加載,并作用在每個路由上。
大家好,我是Doker品牌的Sinbad,歡迎點贊和評論,您的鼓勵是我們持續更新的動力!更多資料請前往Doker 多克