当前位置: 首页 > article >正文

SpringCloud Feign 全局Fallback的另一种实现方式(SpringBoot3.4+)

文章目录

  • 前言
  • 一、定制Fegin
  • 二、定制断路器
    • 1.自定义断路器DefaultCircuitBreaker
    • 2.定义Resilience4JCircuitBreakerFactory bean来替换内置断路器
  • 封装成Starter


前言

之前在SpringBoot2.7+中实现 全局Fallback方式较为复杂,且是从Feign入手,现在从断路器入手,通过捕获异常方式实现。

注意:这里基于SpringBoot3.4实现的,如果是2.7那么又会复杂一点,原因是内置的Resilience4JCircuitBreakerFactory实现的接口未返回接口CircuitBreaker而是实现Resilience4JCircuitBreaker,在3.4版本已修正为接口CircuitBreaker。


一、定制Fegin

请参考之前的实现。

二、定制断路器

因为在未设置断路器时,会抛出NoFallbackAvailableException,所以就通过捕获NoFallbackAvailableException来实现全局Fallback

1.自定义断路器DefaultCircuitBreaker

class DefaultCircuitBreaker implements CircuitBreaker {

    private static final Logger log = LoggerFactory.getLogger(DefaultCircuitBreaker.class);

    private final CircuitBreaker circuitBreaker;

    DefaultCircuitBreaker(CircuitBreaker circuitBreaker) {
        this.circuitBreaker = circuitBreaker;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T> T run(Supplier<T> toRun, Function<Throwable, T> fallback) {
        try {
            return circuitBreaker.run(toRun, fallback);
        } catch (NoFallbackAvailableException e) {
            Throwable cause = e.getCause();
            String errorMessage = cause.getMessage();
            if (cause instanceof FeignException exception && !exception.contentUTF8().isEmpty()) {
                errorMessage = exception.contentUTF8();
            }
            log.error("Using DefaultFallback handle exception", cause);
            return (T) RestResp.error(ExceptionKeys.REMOTE_SERVICE_ERROR, errorMessage);
        }
    }

}

2.定义Resilience4JCircuitBreakerFactory bean来替换内置断路器

    @Bean
    Resilience4JCircuitBreakerFactory resilience4jCircuitBreakerFactory(CircuitBreakerRegistry circuitBreakerRegistry, TimeLimiterRegistry timeLimiterRegistry,
                                                                        @Autowired(required = false) Resilience4jBulkheadProvider bulkheadProvider,
                                                                        Resilience4JConfigurationProperties resilience4JConfigurationProperties) {
        return new Resilience4JCircuitBreakerFactory(circuitBreakerRegistry,
                timeLimiterRegistry, bulkheadProvider, resilience4JConfigurationProperties) {
            @Override
            public CircuitBreaker create(String id) {
                return new DefaultCircuitBreaker(super.create(id));
            }

            @Override
            public CircuitBreaker create(String id, String groupName) {
                return new DefaultCircuitBreaker(super.create(id, groupName));
            }
        };
    }

封装成Starter

  1. 创建一个自动配置类CircuitBreakerAutoConfiguration
@AutoConfiguration(before = Resilience4JAutoConfiguration.class)
@ConditionalOnClass(Resilience4JCircuitBreakerFactory.class)
public class CircuitBreakerAutoConfiguration {

    @Bean
    Resilience4JCircuitBreakerFactory resilience4jCircuitBreakerFactory(CircuitBreakerRegistry circuitBreakerRegistry, TimeLimiterRegistry timeLimiterRegistry,
                                                                        @Autowired(required = false) Resilience4jBulkheadProvider bulkheadProvider,
                                                                        Resilience4JConfigurationProperties resilience4JConfigurationProperties) {
        return new Resilience4JCircuitBreakerFactory(circuitBreakerRegistry,
                timeLimiterRegistry, bulkheadProvider, resilience4JConfigurationProperties) {
            @Override
            public CircuitBreaker create(String id) {
                return new DefaultCircuitBreaker(super.create(id));
            }

            @Override
            public CircuitBreaker create(String id, String groupName) {
                return new DefaultCircuitBreaker(super.create(id, groupName));
            }
        };
    }

}
  1. 将配置类添加到配置文件org.springframework.boot.autoconfigure.AutoConfiguration.imports中

  2. 如果需要配置一个开关来启用CircuitBreakerAutoConfiguration,也可以添加条件注解ConditionalOnProperty如下

@ConditionalOnProperty(prefix = "mcn.circuitbreaker", name = "default.enabled", havingValue = "true", matchIfMissing = true)

http://www.kler.cn/a/487598.html

相关文章:

  • 实现自定义集合类:深入理解C#中的IEnumerable<T>接口
  • 回顾2024年重磅AI发布汇总
  • thinkphp6.0常用设计模式实例
  • docker学习记录:创建mongodb副本集
  • 基于FPGA的出租车里程时间计费器
  • 【题库】人工智能训练师练习题
  • iPad编程新体验:如何用IDE Code App实现远程在线开发告别电脑束缚
  • 大纲笔记幕布的替换
  • 基于伪分布式模式和完全分布式模式部署ZooKeeper集群
  • C# 值类型和引用类型详解
  • Delphi+SQL Server实现的(GUI)户籍管理系统
  • 数据结构-线性表的概念与C语言实现
  • VSCode 插件
  • 使用强化学习训练神经网络玩俄罗斯方块
  • 在 Ubuntu 22.04 上从 Wayland 切换到 X11
  • 定时器类QTimer的简单使用
  • 如何在 Ubuntu 22.04 上部署 BorgBackup 并实现自动化备份教程
  • C++ Json库的使用
  • C语言基础:野指针、空指针、空悬指针
  • 机器学习基础-贝叶斯分类器
  • 第 3 章 HTML5 编程基础教案
  • 【Elasticsearch7.11】postman批量导入少量数据
  • Spring/SpringBoot 的 自动装配与自动配置
  • 如何操作github,gitee,gitcode三个git平台建立镜像仓库机制,这样便于维护项目只需要维护一个平台仓库地址的即可-优雅草央千澈
  • scala_【JVM】概述
  • Zabbix Api使用教程