全域性過濾器

GlobalFilter 介面具有與 GatewayFilter 相同的簽名。這些是特殊過濾器,有條件地應用於所有路由。

此介面及其用法可能會在未來的里程碑版本中更改。

全域性過濾器和 GatewayFilter 的組合排序

當請求匹配到某個路由時,過濾 web 處理器會將 GlobalFilter 的所有例項和路由特定的 GatewayFilter 所有例項新增到過濾器鏈中。這個組合的過濾器鏈透過 org.springframework.core.Ordered 介面進行排序,你可以透過實現 getOrder() 方法來設定排序。

Spring Cloud Gateway 在過濾器邏輯執行時區分“前置(pre)”和“後置(post)”階段(詳見工作原理),優先順序最高的過濾器在“前置”階段最先執行,在“後置”階段最後執行。

以下列表配置了一個過濾器鏈

ExampleConfiguration.java
@Bean
public GlobalFilter customFilter() {
    return new CustomGlobalFilter();
}

public class CustomGlobalFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("custom global filter");
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return -1;
    }
}

閘道器指標過濾器

要啟用閘道器指標,請將 spring-boot-starter-actuator 新增為專案依賴。然後,預設情況下,只要 spring.cloud.gateway.metrics.enabled 屬性未設定為 false,閘道器指標過濾器就會執行。此過濾器添加了一個名為 spring.cloud.gateway.requests 的計時器指標,並帶有以下標籤:

  • routeId:路由 ID。

  • routeUri:API 路由到的 URI。

  • outcome:結果,由 HttpStatus.Series 分類。

  • status:返回給客戶端的請求的 HTTP 狀態。

  • httpStatusCode:返回給客戶端的請求的 HTTP 狀態碼。

  • httpMethod:用於請求的 HTTP 方法。

此外,透過 spring.cloud.gateway.metrics.tags.path.enabled 屬性(預設為 false),你可以啟用帶有路徑標籤的額外指標:

  • path:請求的路徑。

然後可以從 `/actuator/metrics/spring.cloud.gateway.requests` 抓取這些指標,並輕鬆與 Prometheus 整合以建立 Grafana 儀表板。你還可以使用這些有用的指標進行告警,例如參考 告警模板

要啟用 prometheus 端點,請將 micrometer-registry-prometheus 新增為專案依賴。

本地響應快取過濾器

如果相關屬性啟用,LocalResponseCache 將執行:

  • spring.cloud.gateway.global-filter.local-response-cache.enabled:為所有路由啟用全域性快取

  • spring.cloud.gateway.filter.local-response-cache.enabled:啟用相關過濾器以在路由級別使用

此功能使用 Caffeine 為滿足以下所有條件的響應啟用本地快取:

  • 請求是無主體的 GET 請求。

  • 響應具有以下狀態碼之一:HTTP 200 (OK)、HTTP 206 (Partial Content) 或 HTTP 301 (Moved Permanently)。

  • HTTP Cache-Control 頭部允許快取(這意味著請求中沒有 no-store 值,響應中沒有 no-storeprivate 值)。

它接受兩個配置引數:

  • spring.cloud.gateway.filter.local-response-cache.size:設定此路由的快取最大大小,用於逐出條目(單位為 KB、MB 和 GB)。

  • spring.cloud.gateway.filter.local-response-cache.time-to-live:設定快取條目過期時間(以 s 表示秒,m 表示分鐘,h 表示小時)。

如果未配置這些引數,但全域性過濾器已啟用,預設情況下,它會為快取的響應配置 5 分鐘的存活時間。

此過濾器還實現了 HTTP Cache-Control 頭部中 max-age 值的自動計算。如果原始響應中存在 max-age,該值將使用 timeToLive 配置引數中設定的秒數重寫。在後續呼叫中,該值將根據響應過期前剩餘的秒數重新計算。

spring.cloud.gateway.global-filter.local-response-cache.enabled 設定為 false 會停用所有路由的本地響應快取,LocalResponseCache 過濾器允許在路由級別使用此功能。

要啟用此功能,請將 com.github.ben-manes.caffeine:caffeinespring-boot-starter-cache 新增為專案依賴。
如果你的專案建立了自定義的 CacheManager bean,則需要將其標記為 @Primary 或使用 @Qualifier 進行注入。

Forward 路由過濾器

ForwardRoutingFilter 會在交換屬性 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 中查詢 URI。如果 URL 具有 forward 方案(例如 forward:///localendpoint),它會使用 Spring DispatcherHandler 來處理請求。請求 URL 的路徑部分將被轉發 URL 中的路徑覆蓋。未經修改的原始 URL 將被附加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 屬性的列表中。

Netty 路由過濾器

如果位於 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交換屬性中的 URL 具有 httphttps 方案,則 Netty 路由過濾器會執行。它使用 Netty HttpClient 發起下游代理請求。響應被放入 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交換屬性中,供後續過濾器使用。(還有一個實驗性的 WebClientHttpRoutingFilter 執行相同功能,但不需要 Netty。)

Netty 寫入響應過濾器

如果在 ServerWebExchangeUtils.CLIENT_RESPONSE_ATTR 交換屬性中存在 Netty HttpClientResponse,則 NettyWriteResponseFilter 會執行。它在所有其他過濾器完成之後執行,並將代理響應寫回閘道器客戶端響應。(還有一個實驗性的 WebClientWriteResponseFilter 執行相同功能,但不需要 Netty。)

ReactiveLoadBalancerClientFilter

ReactiveLoadBalancerClientFilter 在名為 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 的交換屬性中查詢 URI。如果 URL 具有 lb 方案(例如 lb://myservice),它會使用 Spring Cloud ReactorLoadBalancer 將名稱(本例中的 myservice)解析為實際的主機和埠,並替換相同屬性中的 URI。未經修改的原始 URL 將被附加到 ServerWebExchangeUtils.GATEWAY_ORIGINAL_REQUEST_URL_ATTR 屬性的列表中。過濾器還會檢視 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 屬性,檢查它是否等於 lb。如果是,則適用相同的規則。以下列表配置了一個 ReactiveLoadBalancerClientFilter

application.yml
spring:
  cloud:
    gateway:
      routes:
      - id: myRoute
        uri: lb://service
        predicates:
        - Path=/service/**
預設情況下,當 ReactorLoadBalancer 找不到服務例項時,會返回 503。你可以透過設定 spring.cloud.gateway.loadbalancer.use404=true 來配置閘道器返回 404
ReactiveLoadBalancerClientFilter 返回的 ServiceInstanceisSecure 值會覆蓋傳送到閘道器的請求中指定的方案(scheme)。例如,如果請求透過 HTTPS 進入閘道器,但 `ServiceInstance` 表明它不安全,則下游請求會透過 HTTP 發起。反之亦然。但是,如果在閘道器配置中為路由指定了 GATEWAY_SCHEME_PREFIX_ATTR,則會剝離字首,並且路由 URL 中產生的方案會覆蓋 ServiceInstance 配置。
閘道器支援所有 LoadBalancer 功能。你可以在 Spring Cloud Commons 文件中瞭解更多資訊。

RouteToRequestUrl 過濾器

如果在 ServerWebExchangeUtils.GATEWAY_ROUTE_ATTR 交換屬性中存在 Route 物件,則 RouteToRequestUrlFilter 會執行。它會根據請求 URI 建立一個新的 URI,並使用 Route 物件的 URI 屬性進行更新。新的 URI 被放置在 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交換屬性中。

如果 URI 具有方案字首,例如 lb:ws://serviceid,則會從 URI 中剝離 lb 方案,並將其放置在 ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR 中,供過濾器鏈後續使用。

Websocket 路由過濾器

如果位於 ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR 交換屬性中的 URL 具有 wswss 方案,則 websocket 路由過濾器會執行。它使用 Spring WebSocket 基礎設施將 websocket 請求轉發到下游。

你可以透過在 URI 前面新增 lb 來對 websocket 進行負載均衡,例如 lb:ws://serviceid

如果你使用 SockJS 作為普通 HTTP 的回退方案,你應該配置正常的 HTTP 路由以及 websocket 路由。

以下列表配置了一個 websocket 路由過濾器

application.yml
spring:
  cloud:
    gateway:
      routes:
      # SockJS route
      - id: websocket_sockjs_route
        uri: https://:3001
        predicates:
        - Path=/websocket/info/**
      # Normal Websocket route
      - id: websocket_route
        uri: ws://:3001
        predicates:
        - Path=/websocket/**

將交換標記為已路由

閘道器路由 ServerWebExchange 後,它透過向交換屬性中新增 gatewayAlreadyRouted 來將該交換標記為“已路由”。一旦請求被標記為已路由,其他路由過濾器將不會再次路由該請求,從而跳過該過濾器。有一些方便的方法可以用來將交換標記為已路由或檢查交換是否已路由。

  • ServerWebExchangeUtils.isAlreadyRouted 接受一個 ServerWebExchange 物件,並檢查它是否已“路由”。

  • ServerWebExchangeUtils.setAlreadyRouted 接受一個 ServerWebExchange 物件,並將其標記為“已路由”。