CircuitBreaker 过滤器
CircuitBreaker Filter
Spring Cloud CircuitBreaker GatewayFilter 工厂使用 Spring Cloud CircuitBreaker API 将 Gateway 路由包装在断路器内。Spring Cloud CircuitBreaker 支持多个可与 Spring Cloud Gateway 配合使用的库。Spring Cloud 默认支持 Resilience4J。
要启用 Spring Cloud CircuitBreaker 过滤器,您需要在类路径中添加 spring-cloud-starter-circuitbreaker-reactor-resilience4j。以下示例配置了一个 Spring Cloud CircuitBreaker 过滤器:
spring:
cloud:
gateway:
server:
webmvc:
routes:
- id: circuitbreakernofallback
uri: https://example.org
predicates:
- Path=/anything/circuitbreakernofallback
filters:
- CircuitBreaker=myCircuitBreaker
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。如果触发了降级处理,请求将被转发到与该 URI 匹配的控制器。以下示例展示了如何配置此类降级处理:
spring:
cloud:
gateway:
server:
webmvc:
routes:
- id: circuitbreaker_route
uri: https://example.org
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
下面的清单在 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。
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 来定义网关应用程序内的内部控制器或处理程序。不过,您也可以将请求重新路由到外部应用程序中的控制器或处理程序,如下所示:
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://localhost:9994"))
.build());
}
}
在这个例子中,网关应用程序中没有 fallback 端点或处理程序。然而,在另一个应用程序中存在一个,注册在 [localhost:9994](http://localhost:9994) 下。
当请求被转发到后备方案时,Spring Cloud CircuitBreaker Gateway 过滤器还会提供导致此情况的 Throwable。该异常会作为 MvcUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 属性添加到 ServerRequest 中,可在网关应用程序内处理后备方案时使用。
对于外部控制器/处理器的场景,可以通过添加包含异常详情的头部信息来实现。你可以在FallbackHeaders过滤器章节中找到更多相关信息。
基于状态码触发熔断器
在某些情况下,您可能希望根据路由返回的状态码来触发熔断器。熔断器配置对象接受一个状态码列表,如果返回的状态码在列表中,就会触发熔断器。在设置触发熔断器的状态码时,您可以使用状态码的整数值,也可以使用 HttpStatus 枚举的字符串表示形式。
spring:
cloud:
gateway:
server:
webmvc:
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"
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();
}
}
无错误恢复
当断路器跳闸或遇到错误时,你可以通过将 resumeWithoutError 设置为 true 来配置它,使其在不将错误传播给客户端的情况下恢复。这对于非关键服务非常有用,即使断路器失败,你也希望继续处理。
当 resumeWithoutError 设置为 true 时,超时异常和熔断器开启异常(CallNotPermittedException)仍会返回其对应的 HTTP 状态码(504 Gateway Timeout 和 503 Service Unavailable)。只有其他未处理的异常才会导致成功响应。
spring:
cloud:
gateway:
mvc:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
resumeWithoutError: true
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> gatewayRouterFunctionsCircuitBreakerResumeWithoutError() {
return route("circuitbreaker_route")
.route(path("/consumingServiceEndpoint"), http())
.filter(lb("backing-service"))
.filter(circuitBreaker(config -> config.setId("myCircuitBreaker").setResumeWithoutError(true)))
.build();
}
}