CircuitBreaker Filter

Spring Cloud CircuitBreaker GatewayFilter 工厂使用 Spring Cloud CircuitBreaker API,在一个断路器中封装网关路由。Spring Cloud CircuitBreaker 支持多种库,可以与 Spring Cloud Gateway 结合使用。Spring Cloud 直接支持 Resilience4J。

The Spring Cloud CircuitBreaker GatewayFilter factory uses the Spring Cloud CircuitBreaker APIs to wrap Gateway routes in a circuit breaker. Spring Cloud CircuitBreaker supports multiple libraries that can be used with Spring Cloud Gateway. Spring Cloud supports Resilience4J out of the box.

若要启用 Spring Cloud CircuitBreaker 过滤器,你需要将 spring-cloud-starter-circuitbreaker-reactor-resilience4j 放到类路径上。以下示例配置了一个 Spring Cloud CircuitBreaker 过滤器:

To enable the Spring Cloud CircuitBreaker filter, you need to place spring-cloud-starter-circuitbreaker-reactor-resilience4j on the classpath. The following example configures a Spring Cloud CircuitBreaker filter:

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();
    }
}

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

To configure the circuit breaker, see the configuration for the underlying circuit breaker implementation you are using.

Spring Cloud CircuitBreaker 筛选器还可以接受一个可选的 fallbackUri 参数。当前仅支持 forward: 模式的 URI。如果调用回退,请求将转发到 URI 匹配的控制器。以下示例配置这样的回退:

The Spring Cloud CircuitBreaker filter can also accept an optional fallbackUri parameter. Currently, only forward: schemed URIs are supported. If the fallback is called, the request is forwarded to the controller matched by the URI. The following example configures such a fallback:

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 中执行相同操作:

The following listing does the same thing in 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。

This example forwards to the /inCaseofFailureUseThis URI when the circuit breaker fallback is called.

断路器还支持 fallbackUri 中的 URI 变量。这允许执行更复杂的路由选项,例如使用 PathPattern expression 转发原始主机或 URL 路径的部分内容。

CircuitBreaker also supports URI variables in the fallbackUri. This allows more complex routing options, like forwarding sections of the original host or url path using PathPattern expression.

在下面的示例中,调用 consumingServiceEndpoint/users/1 将被重定向到 inCaseOfFailureUseThis/users/1

In the example below the call consumingServiceEndpoint/users/1 will be redirected to 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 在网关应用程序中定义内部控制器或处理程序。但是,您还可以按如下方式将请求重新路由到外部应用程序中的控制器或处理程序:

The primary scenario is to use the fallbackUri to define an internal controller or handler within the gateway application. However, you can also reroute the request to a controller or handler in an external application, as follows:

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 下注册。

In this example, there is no fallback endpoint or handler in the gateway application. However, there is one in another application, registered under http://localhost:9994.

如果请求被转发到后备,Spring Cloud CircuitBreaker Gateway 过滤器还会提供导致该情况的 Throwable。它将作为 MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 属性添加到 ServerRequest,以便在网关应用程序中处理后备时使用。

In case of the request being forwarded to fallback, the Spring Cloud CircuitBreaker Gateway filter also provides the Throwable that has caused it. It is added to the ServerRequest as the MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR attribute that can be used when handling the fallback within the gateway application.

对于外部控制器/处理程序场景,可以使用异常详细信息添加标头。您可以在 FallbackHeaders Filters section 中找到有关如何执行此操作的更多信息。

For the external controller/handler scenario, headers can be added with exception details. You can find more information on doing so in the FallbackHeaders Filters section.

Tripping The Circuit Breaker On Status Codes

在某些情况下,您可能希望根据从它所包装的路由返回的状态码触发断路器。断路器配置对象采用一个状态码列表,如果返回,将导致断路器触发。在设置状态码以触发断路器时,您可以使用具有状态码值或 HttpStatus 枚举的字符串表示形式的整数。

In some cases you might want to trip a circuit breaker based on the status code returned from the route it wraps. The circuit breaker config object takes a list of status codes that if returned will cause the circuit breaker to be tripped. When setting the status codes you want to trip the circuit breaker you can either use an integer with the status code value or the String representation of the HttpStatus enumeration.

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();
    }
}