Spring Boot中调用CircuitBreakerFactory.create是否每次生成新熔断器实例
问题结论
你担心的统计数据丢失问题不会发生,circuitBreakerFactory.create() 传入相同熔断器ID时不会重复创建独立的新实例。
底层实现逻辑
- Spring Cloud Circuit Breaker 对
CircuitBreakerFactory的默认实现内置了实例缓存机制,你在代码中传入的字符串参数"circuitbreaker"是熔断器的唯一标识ID。 - 首次调用
create("circuitbreaker")时,工厂会初始化对应的熔断器实例,后续所有传入相同ID的create调用,都会直接返回缓存中的同一份实例引用,不会生成新的独立实例。 - 对接Resilience4j实现时,这套逻辑本质是封装了Resilience4j自带的
CircuitBreakerRegistry缓存能力,所有同名称的熔断器默认以单实例形式存在于整个应用上下文内,完全符合熔断器全局统计的设计要求。
代码写法说明
示例代码把create逻辑写在方法内部是完全合法的,唯一的多余开销只是每次调用会多走一次缓存查询,性能影响可以忽略不计。如果要更符合最佳实践,可以将熔断器实例作为类成员变量初始化,效果完全一致,参考写法如下:
@Service public class AlbumService { private static final Logger LOGGER = LoggerFactory.getLogger(AlbumService.class); @Autowired private CircuitBreakerFactory circuitBreakerFactory; private RestTemplate restTemplate = new RestTemplate(); // 类成员变量保存熔断器实例 private CircuitBreaker circuitBreaker; // 类初始化时创建一次熔断器 @PostConstruct public void initCircuitBreaker() { this.circuitBreaker = circuitBreakerFactory.create("circuitbreaker"); } public String getAlbumList() { String url = "https://jsonplaceholder.typicode.com/albums"; return circuitBreaker.run(() -> restTemplate.getForObject(url, String.class), throwable -> getDefaultAlbumList()); } private String getDefaultAlbumList() { try { return new String(Files.readAllBytes(Paths.get(getClass().getClassLoader().getResource("fallback-album-list.json").toURI()))); } catch (Exception e) { LOGGER.error("error occurred while reading the file", e); } return null; } }
内容的提问来源于stack exchange,提问作者Akash Sharma
相关产品推荐
相关产品推荐

