CircuitBreaker Filter

Spring Cloud CircuitBreaker GatewayFilter 工厂使用 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: circuitbreaker_route
          uri: https://example.org
          filters:
          - CircuitBreaker=myCircuitBreaker
GatewaySampleApplication.java
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("https://example.org"))
                .filter(circuitBreaker("mycb3"))
                .build();
    }
}

要配置断路器,请参阅所使用基础断路器实现的配置。

Spring Cloud CircuitBreaker 筛选器还可以接受一个可选的 fallbackUri 参数。当前仅支持 forward: 模式的 URI。如果调用回退,请求将转发到 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.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("https://example.org"))
                .filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis")))
                .build();
    }
}

此示例在调用断路器后备时将转发到 /inCaseofFailureUseThis URI。 断路器还支持 fallbackUri 中的 URI 变量。这允许执行更复杂的路由选项,例如使用 PathPattern expression 转发原始主机或 URL 路径的部分内容。 在下面的示例中,调用 consumingServiceEndpoint/users/1 将被重定向到 inCaseOfFailureUseThis/users/1

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.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("https://example.org"))
                .filter(circuitBreaker("myCircuitBreaker", URI.create("forward:/inCaseOfFailureUseThis/{segments}")))
                .build();
    }
}

主要场景是使用 fallbackUri 在网关应用程序中定义内部控制器或处理程序。但是,您还可以按如下方式将请求重新路由到外部应用程序中的控制器或处理程序:

GatewaySampleApplication.java
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("http://localhost:9994"))
                .build());
    }
}

在本例中,网关应用程序中没有 fallback 端点或处理程序。但是,在另一个应用程序中有一个,在 http://localhost:9994 下注册。 如果请求被转发到后备,Spring Cloud CircuitBreaker Gateway 过滤器还会提供导致该情况的 Throwable。它将作为 MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 属性添加到 ServerRequest,以便在网关应用程序中处理后备时使用。 对于外部控制器/处理程序场景,可以使用异常详细信息添加标头。您可以在 FallbackHeaders Filters section 中找到有关如何执行此操作的更多信息。

Tripping The Circuit Breaker On Status Codes

在某些情况下,您可能希望根据从它所包装的路由返回的状态码触发断路器。断路器配置对象采用一个状态码列表,如果返回,将导致断路器触发。在设置状态码以触发断路器时,您可以使用具有状态码值或 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();
    }
}