本文目录导读:

我来为您提供一个完整的Java熔断恢复案例,使用Spring Cloud Circuit Breaker(Resilience4j实现):
项目依赖配置
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Resilience4j Circuit Breaker -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>
<!-- Resilience4j 核心 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>1.7.1</version>
</dependency>
<!-- Actuator 用于监控-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
配置文件 application.yml
server:
port: 8080
spring:
application:
name: circuit-breaker-demo
# Resilience4j 熔断器配置
resilience4j:
circuitbreaker:
instances:
externalApi:
# 环形缓冲区大小(关闭状态)
ringBufferSizeInClosedState: 10
# 半开状态缓冲区大小
ringBufferSizeInHalfOpenState: 5
# 失败率阈值
failureRateThreshold: 50
# 等待时间(自动从打开到半开)
waitDurationInOpenState: 10000
# 慢调用阈值
slowCallDurationThreshold: 2000
# 慢调用失败率
slowCallRateThreshold: 50
# 记录异常
recordExceptions:
- java.lang.Exception
# 忽略的异常
ignoreExceptions:
- com.example.demo.exception.BusinessException
# 超时配置
timelimiter:
instances:
externalApi:
# 超时时间
timeoutDuration: 3s
# 取消运行中的线程
cancelRunningFuture: true
management:
endpoints:
web:
exposure:
include: "*"
endpoint:
health:
show-details: always
服务类 Demo(核心示例)
package com.example.demo.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import io.github.resilience4j.circuitbreaker.annotation.CircuitBreaker;
import io.github.resilience4j.ratelimiter.annotation.RateLimiter;
import io.github.resilience4j.retry.annotation.Retry;
import java.time.LocalDateTime;
@Slf4j
@Service
public class ExternalService {
private final RestTemplate restTemplate;
// 模拟状态变量用于演示
private int callCount = 0;
private int successCount = 0;
public ExternalService() {
this.restTemplate = new RestTemplate();
}
/**
* 带熔断器的外部调用方法
* name 对应 yml 中的配置名称
*/
@CircuitBreaker(name = "externalApi", fallbackMethod = "fallbackGetData")
@Retry(name = "externalApi", fallbackMethod = "fallbackGetData")
@RateLimiter(name = "externalApi", fallbackMethod = "fallbackGetData")
public String getExternalData() {
callCount++;
log.info("=== 开始调用外部服务 (调用次数: {}), 时间: {} ===", callCount, LocalDateTime.now());
// 模拟外部服务调用
String result = callExternalApi();
if (result.contains("成功")) {
successCount++;
log.info("调用成功,当前成功率: {}/{}", successCount, callCount);
return "External Data Result: " + result;
}
throw new RuntimeException("外部服务调用失败");
}
/**
* 模拟外部API调用
* 用于演示不同的调用结果
*/
private String callExternalApi() {
// 这里可以替换成真实的API调用
// 模拟不同的调用场景
// 用于测试:每5次调用中,第3、4次会失败
if (callCount % 5 == 3 || callCount % 5 == 4) {
try {
Thread.sleep(5000); // 模拟慢调用
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
throw new RuntimeException("外部服务响应超时");
}
// 模拟网络异常
if (callCount > 10 && successCount < callCount / 2) {
throw new RuntimeException("Network connection refused");
}
return "成功-" + callCount;
}
/**
* 熔断降级方法
*/
public String fallbackGetData(Throwable t) {
log.error("熔断器触发,降级处理!错误信息: {}", t.getMessage());
return "【降级响应】服务暂时不可用,请稍后重试,降级时间: " + LocalDateTime.now();
}
/**
* 带自定义异常的熔断
*/
@CircuitBreaker(name = "externalApi", fallbackMethod = "fallbackWithCustomException")
public String getUserData(String userId) {
if ("123".equals(userId)) {
throw new IllegalArgumentException("用户ID不存在");
}
return "用户数据: " + userId;
}
public String fallbackWithCustomException(String userId, Throwable t) {
if (t instanceof IllegalArgumentException) {
return "参数错误: " + t.getMessage();
}
return "系统错误,请稍后重试";
}
/**
* 重置熔断器状态(用于测试)
*/
public void resetCircuitBreaker() {
callCount = 0;
successCount = 0;
}
public int getCallCount() {
return callCount;
}
public int getSuccessCount() {
return successCount;
}
}
Controller 控制器
package com.example.demo.controller;
import com.example.demo.service.ExternalService;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import lombok.RequiredArgsConstructor;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
@RestController
@RequestMapping("/api")
@RequiredArgsConstructor
public class CircuitBreakerController {
private final ExternalService externalService;
private final CircuitBreakerRegistry circuitBreakerRegistry;
/**
* 正常调用接口
*/
@GetMapping("/external")
public String getExternalData() {
return externalService.getExternalData();
}
/**
* 获取熔断器状态
*/
@GetMapping("/breaker/status")
public String getBreakerStatus() {
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("externalApi");
return String.format(
"状态: %s, 失败率: %.2f%%, 调用次数: %d",
circuitBreaker.getState(),
circuitBreaker.getMetrics().getFailureRate(),
circuitBreaker.getMetrics().getNumberOfSuccessfulCallsWithoutRetry() +
circuitBreaker.getMetrics().getNumberOfFailedCallsWithoutRetry()
);
}
/**
* 重置熔断器
*/
@PostMapping("/breaker/reset")
public String resetBreaker() {
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("externalApi");
circuitBreaker.reset();
externalService.resetCircuitBreaker();
return "熔断器已重置,当前状态: " + circuitBreaker.getState();
}
/**
* 手动触发打开熔断器
*/
@PostMapping("/breaker/force-open")
public String forceOpenBreaker() {
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("externalApi");
circuitBreaker.transitionToOpenState();
return "熔断器已强制打开";
}
/**
* 手动关闭熔断器
*/
@PostMapping("/breaker/force-close")
public String forceCloseBreaker() {
CircuitBreaker circuitBreaker = circuitBreakerRegistry.circuitBreaker("externalApi");
circuitBreaker.transitionToCloseState();
return "熔断器已强制关闭";
}
}
自定义配置类
package com.example.demo.config;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.circuitbreaker.CircuitBreakerRegistry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.time.Duration;
@Configuration
public class CircuitBreakerConfig {
/**
* 编程式配置熔断器(可选,也可以使用yml配置)
*/
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 失败率阈值
.waitDurationInOpenState(Duration.ofSeconds(10)) // 等待时间
.ringBufferSizeInClosedState(10) // 关闭状态缓冲区大小
.ringBufferSizeInHalfOpenState(5) // 半开状态缓冲区大小
.slowCallDurationThreshold(Duration.ofSeconds(2)) // 慢调用阈值
.build();
return CircuitBreakerRegistry.of(config);
}
}
全局异常处理
package com.example.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleException(Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("系统异常: " + e.getMessage());
}
@ExceptionHandler(BusinessException.class)
public ResponseEntity<String> handleBusinessException(BusinessException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("业务异常: " + e.getMessage());
}
}
测试示例
package com.example.demo.controller;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class CircuitBreakerIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void testCircuitBreakerBehavior() {
// 模拟多次调用触发熔断
for (int i = 0; i < 20; i++) {
ResponseEntity<String> response =
restTemplate.getForEntity("/api/external", String.class);
System.out.println("第 " + (i+1) + " 次调用: " + response.getBody());
// 分段停止
if (i == 4 || i == 9 || i == 14 || i == 19) {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// 检查熔断器状态
ResponseEntity<String> statusResponse =
restTemplate.getForEntity("/api/breaker/status", String.class);
System.out.println("熔断器状态: " + statusResponse.getBody());
}
}
监控和观察
添加监控端点和查看指标:
package com.example.demo.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Counter;
@RestController
public class MetricsController {
private final MeterRegistry meterRegistry;
public MetricsController(MeterRegistry meterRegistry) {
this.meterRegistry = meterRegistry;
}
@GetMapping("/metrics")
public Object getMetrics() {
return meterRegistry.getMeters().stream()
.map(meter -> meter.getId().getName())
.distinct()
.collect(java.util.stream.Collectors.toList());
}
}
使用说明
- 启动应用:运行主启动类即可看到效果
- 调用接口:
GET /api/external- 测试熔断调用GET /api/breaker/status- 查看熔断器状态POST /api/breaker/reset- 重置熔断器
- 观察日志:通过日志观察熔断器的状态变化
- 访问监控:
http://localhost:8080/actuator/health查看健康状态
这个案例展示了:
- 熔断器的基本配置和使用
- 降级回退机制
- 动态状态管理
- 监控指标
- 测试示例
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播