CircuitBreaker GatewayFilter 工厂
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 GatewayFilter:
application.yml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: https://example.org
filters:
- CircuitBreaker=myCircuitBreaker要配置断路器本身,请参阅您正在使用的底层断路器实现(如 Resilience4J)的配置文档:
Spring Cloud CircuitBreaker 过滤器还可以接受一个可选的 fallbackUri 参数。目前,仅支持带有 forward: 协议(scheme)的 URI。如果触发了回退(Fallback)机制,请求将被转发到与该 URI 匹配的控制器。
以下示例配置了带有回退机制的路由:
application.yml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis
- RewritePath=/consumingServiceEndpoint, /backingServiceEndpoint以下代码展示了如何使用 Java 配置实现相同的功能:
Application.java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis"))
.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}在此示例中,当断路器回退被触发时,请求会转发到 /inCaseOfFailureUseThis。请注意,此示例还演示了(可选的)Spring Cloud LoadBalancer 负载均衡(由目标 URI 的 lb 前缀定义)。
CircuitBreaker 的 fallbackUri 还支持 URI 变量。这允许更复杂的路由选项,例如使用 PathPattern 表达式 将原始主机或 URL 路径的一部分转发到回退处理器。
在下面的示例中,调用 /consumingServiceEndpoint/users/1 将被重定向到 /inCaseOfFailureUseThis/users/1。
application.yml
spring:
cloud:
gateway:
routes:
- id: circuitbreaker_route
uri: lb://backing-service:8088
predicates:
- Path=/consumingServiceEndpoint/{*segments}
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis/{segments}主要场景是使用 fallbackUri 在网关应用程序内部定义一个内部控制器或处理程序。但是,您也可以将请求重定向到外部应用程序中的控制器或处理程序,如下所示:
application.yml
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: lb://ingredients
predicates:
- Path=//ingredients/**
filters:
- name: CircuitBreaker
args:
name: fetchIngredients
fallbackUri: forward:/fallback
- id: ingredients-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback在这个例子中:
- 网关应用程序中没有
/fallback端点或处理程序。 - 但是,在另一个应用程序(运行在
localhost:9994)中有一个处理程序。 - 网关定义了第二个路由
ingredients-fallback,用于匹配/fallback并将其转发到外部服务。
如果请求被转发到备用方案,Spring Cloud CircuitBreaker Gateway 过滤器还会提供导致该故障的原因。该异常原因会作为 ServerWebExchangeUtils.CIRCUITBREAKER_EXECUTION_EXCEPTION_ATTR 属性添加到 ServerWebExchange 中,以便在处理备用方案时使用。
对于外部控制器/处理程序场景,可以添加包含异常详细信息的 Header。您可以在 FallbackHeaders GatewayFilter Factory 部分找到更多相关信息。
根据状态码触发熔断 (Tripping The Circuit Breaker On Status Codes)
在某些情况下,您可能需要根据路由返回的 HTTP 状态码来触发断路器。断路器配置对象接受一个状态码列表,当返回列表中的某个状态码时,断路器就会跳闸。 设置状态码时,您可以使用状态码的整数值(如 500),也可以使用 HttpStatus 枚举的字符串表示形式(如 "INTERNAL_SERVER_ERROR")。
application.yml
spring:
cloud:
gateway:
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"Application.java
@Bean
public RouteLocator routes(RouteLocatorBuilder builder) {
return builder.routes()
.route("circuitbreaker_route", r -> r.path("/consumingServiceEndpoint")
.filters(f -> f.circuitBreaker(c -> c.name("myCircuitBreaker").fallbackUri("forward:/inCaseOfFailureUseThis").addStatusCode("INTERNAL_SERVER_ERROR"))
.rewritePath("/consumingServiceEndpoint", "/backingServiceEndpoint")).uri("lb://backing-service:8088")
.build();
}通俗易懂的教学 —— “家里的保险丝”
想象一下,你家里有很多电器(电视、冰箱、微波炉),这些就像是你的微服务。而 Spring Cloud Gateway 就像是你家里的总电闸/配电箱。
1. 什么是 CircuitBreaker(断路器)?
通俗解释: CircuitBreaker 就是保险丝。
- 正常情况:电流顺畅通过,电器正常工作(请求正常转发给微服务)。
- 出故障了:如果微波炉突然短路了(微服务挂了或者响应极慢),电流过大。
- 没有保险丝:电线会烧坏,甚至引发火灾,把隔壁冰箱也烧坏(由于请求堆积,耗尽网关资源,导致整个网关崩溃,所有服务都不可用 —— 这叫雪崩效应)。
- 有保险丝:保险丝“啪”的一声断开(熔断)。微波炉没电了,但是电视和冰箱还能正常用。网关会告诉用户:“微波炉暂时坏了,请稍后再试”,而不是让用户一直干等。
2. 配置里的关键参数是什么意思?
name: myCircuitBreaker:给这个保险丝起个名字。fallbackUri: forward:/fallback:这就是备用方案(兜底)。- 场景:你点外卖,系统去调用“商家服务”获取菜单。
- 故障:“商家服务”挂了,超时了。
- 熔断发生:保险丝断开。
- Fallback:网关自动把请求转发到
/fallback。这个/fallback可能返回一张图片:“哎呀,系统繁忙,请稍后再试”,或者返回一个缓存的旧菜单。 - 好处:用户看到的是友好的提示,而不是由浏览器报出的
500 Internal Server Error或者在那转圈圈转到死。
3. 什么是“根据状态码熔断”?
默认情况下,只有微服务完全连不上或者超时,保险丝才会断。 但是,有时候微服务虽然连上了,却返回了错误的信息,比如 500(服务器内部错误)。
- 配置
statusCodes: 500:意思是告诉网关,“只要那个微服务敢给我返回 500 错误,我就当它坏了,直接拉闸!走备用方案!”
4. 总结
在 Spring Cloud Gateway 中配置 CircuitBreaker 只有三步:
- 加依赖:买保险丝(引入
spring-cloud-starter-circuitbreaker-reactor-resilience4j)。 - 配过滤器:把保险丝装进电路里(在 yaml 里配置
filters: - CircuitBreaker=...)。 - 写兜底逻辑:想好保险丝断了该怎么办(写一个
/fallback接口返回友好提示)。
这样,你的系统就从“一碰就倒”变成了“坚不可摧”的堡垒!