CircuitBreaker 過濾器

Spring Cloud CircuitBreaker GatewayFilter factory 使用 Spring Cloud CircuitBreaker API 將閘道器路由封裝在斷路器中。Spring Cloud CircuitBreaker 支援多種可與 Spring Cloud Gateway 一起使用的庫。Spring Cloud 開箱即用地支援 Resilience4J。

要啟用 Spring Cloud CircuitBreaker 過濾器,您需要在類路徑中放置 spring-cloud-starter-circuitbreaker-reactor-resilience4j。以下示例配置了 Spring Cloud CircuitBreaker 過濾器

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: circuitbreakernofallback
          uri: https://example.org
          predicates:
          - Path=/anything/circuitbreakernofallback
          filters:
          - CircuitBreaker=myCircuitBreaker
GatewaySampleApplication.java
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerNoFallback() {
        return route("circuitbreakernofallback")
            .route(path("/anything/circuitbreakernofallback"), http())
            .before(uri("https://example.org"))
            .filter(circuitBreaker("myCircuitBreaker"))
            .build();
    }
}

要配置斷路器,請參閱您正在使用的底層斷路器實現的配置。

Spring Cloud CircuitBreaker 過濾器還可以接受一個可選的 fallbackUri 引數。目前,僅支援 forward: 方案的 URI。如果呼叫了回退(fallback),請求將被轉發到與該 URI 匹配的控制器。以下示例配置了這樣的回退

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: circuitbreaker_route
          uri: https://example.org
          predicates:
          - Path=/consumingServiceEndpoint
          filters:
          - name: CircuitBreaker
            args:
              name: myCircuitBreaker
              fallbackUri: forward:/inCaseOfFailureUseThis

以下列表在 Java 中實現同樣的功能

GatewaySampleApplication.java
import java.net.URI;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
        return route("circuitbreaker_route")
            .route(path("/consumingServiceEndpoint"), http())
            .before(uri("https://example.org"))
            .filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis")))
            .build();
    }
}

當呼叫斷路器回退時,此示例將請求轉發到 /inCaseofFailureUseThis URI。

CircuitBreaker 也支援在 fallbackUri 中使用 URI 變數。這允許更復雜的路由選項,例如使用 PathPattern 表示式轉發原始主機或 URL 路徑的部分內容。

在下面的示例中,呼叫 consumingServiceEndpoint/users/1 將被重定向到 inCaseOfFailureUseThis/users/1

GatewaySampleApplication.java
import java.net.URI;
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
        return route("circuitbreaker_route")
            .route(path("/consumingServiceEndpoint/{*segments}"), http())
            .before(uri("https://example.org"))
            .filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis/{segments}")))
            .build();
    }
}

主要場景是使用 fallbackUri 在閘道器應用程式內部定義一個控制器或處理器。但是,您也可以將請求重新路由到外部應用程式中的控制器或處理器,如下所示

GatewaySampleApplication.java
import static org.springframework.cloud.gateway.server.mvc.filter.BeforeFilterFunctions.uri;
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
import static org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions.lb;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallbackToGatewayRoute() {
        return route("ingredients")
                .route(path("/ingredients/**"), http())
                .filter(lb("ingredients"))
                .filter(circuitBreaker("fetchIngredients", URI.create("forward:/fallback")))
                .build()
            .and(route("ingredients-fallback")
                .route(path("/fallback"), http())
                .before(uri("https://:9994"))
                .build());
    }
}

在此示例中,閘道器應用程式中沒有 fallback 端點或處理器。但是,在另一個應用程式中存在一個,註冊在 localhost:9994 下。

在請求被轉發到回退的情況下,Spring Cloud CircuitBreaker Gateway 過濾器還會提供導致回退的 Throwable。它作為 MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 屬性新增到 ServerRequest 中,可以在閘道器應用程式內部處理回退時使用。

對於外部控制器/處理器場景,可以新增包含異常詳細資訊的頭部。您可以在FallbackHeaders 過濾器部分中找到更多相關資訊。

根據狀態碼觸發斷路器

在某些情況下,您可能希望根據其包裝的路由返回的狀態碼來觸發斷路器。斷路器配置物件接受一個狀態碼列表,如果返回這些狀態碼,將導致斷路器被觸發。設定要觸發斷路器的狀態碼時,可以使用狀態碼值的整數或 HttpStatus 列舉的字串表示形式。

application.yml
spring:
  cloud:
    gateway:
      mvc:
        routes:
        - id: circuitbreaker_route
          uri: lb://backing-service:8088
          predicates:
          - Path=/consumingServiceEndpoint
          filters:
          - name: CircuitBreaker
            args:
              name: myCircuitBreaker
              fallbackUri: forward:/inCaseOfFailureUseThis
              statusCodes:
                - 500
                - "NOT_FOUND"
GatewaySampleApplication.java
import java.net.URI;
import static org.springframework.cloud.gateway.server.mvc.filter.CircuitBreakerFilterFunctions.circuitBreaker;
import static org.springframework.cloud.gateway.server.mvc.filter.LoadBalancerFilterFunctions.lb;
import static org.springframework.cloud.gateway.server.mvc.handler.GatewayRouterFunctions.route;
import static org.springframework.cloud.gateway.server.mvc.handler.HandlerFunctions.http;

@Configuration
class RouteConfiguration {

    @Bean
    public RouterFunction<ServerResponse> gatewayRouterFunctionsCircuitBreakerFallback() {
        return route("circuitbreaker_route")
                .route(path("/consumingServiceEndpoint"), http())
                .filter(lb("backing-service"))
				.filter(circuitBreaker(config -> config.setId("myCircuitBreaker").setFallbackUri("forward:/inCaseOfFailureUseThis").setStatusCodes("500", "NOT_FOUND")))
                .build();
    }
}