SpringBoot升级后Hystrix没了以及3个替代方案分享

 更新时间:2026年04月18日 15:34:28   作者:真实的菜  
这篇文章主要介绍了SpringBoot升级后Hystrix没了以及3个替代方案分享,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

写在前面

公司项目要从 Spring Boot 2.2.x 升级到 2.7,领导让我负责调研。

拿到手一看,好家伙,Hystrix 停更了?Feign 的 fallback 怎么报错了?Ribbon 也不推荐用了?

网上的文档要么太深奥,要么太简单。没办法,只能自己一点点啃,顺便把踩坑经历记下来。

如果你也是新手,希望这篇笔记能帮到你。

环境信息

  • Spring Boot: 2.2.x → 2.7.18
  • Spring Cloud: Hoxton.SR9 → 2021.x
  • Hystrix: 1.5.x(停更)→ Resilience4j 1.7.x
  • Ribbon: 2.x(停更)→ Spring Cloud LoadBalancer
  • OpenFeign: 2.2.x → 3.1.x

坑 1:Hystrix 停更了,用啥替代?

我当时以为很简单

直接升级 Spring Boot 和 Spring Cloud,心想依赖会自动更新…

<!-- 我当时看到这个配置,心想这不简单吗 -->
<spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.x</spring-cloud.version>

结果启动失败:

***************************
APPLICATION FAILED TO RUN
***************************

Description:

The Spring Cloud project contains incompatible modules: 
spring-cloud-starter-netflix-hystrix is not compatible with 
Spring Cloud 2021.x and later.

我当时就懵了。啥?Hystrix 不兼容?

问题根源

后来查资料才明白:

  1. Hystrix 停更:Netflix Hystrix 从 2020 年开始就进入维护模式,不再更新
  2. Spring Cloud 移除:Spring Cloud 2020.x(Illford)开始移除了对 Hystrix 的支持
  3. 官方推荐:Spring 官方推荐使用 Resilience4j 作为替代方案

好家伙,原来是时代的眼泪。

解决方案

用 Resilience4j 替代 Hystrix

<!-- 移除 Hystrix 依赖 -->
<!-- 
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
-->
<!-- 添加 Resilience4j 依赖 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-circuitbreaker-resilience4j</artifactId>
</dependency>

配置 Resilience4j

# application.yml
resilience4j:
  circuitbreaker:
    instances:
      backendA:  # 服务名
        registerHealthIndicator: true
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 10000
        permittedNumberOfCallsInHalfOpenState: 5
        automaticTransitionFromOpenToHalfOpenEnabled: true
        timeout:
          timeout: 3s
          cancelRunningFuture: false

使用方式

@Service
public class MyService {
    
    @CircuitBreaker(name = "backendA", fallbackMethod = "fallback")
    public String callExternalService() {
        // 调用外部服务
        return "success";
    }
    
    // fallback 方法
    public String fallback(Exception e) {
        log.error("服务调用失败,执行 fallback: {}", e.getMessage());
        return "fallback result";
    }
}

教训:Hystrix 已经停更了,别再用!官方推荐 Resilience4j!

坑 2:Feign 的 FallbackFactory 报错了

我只排除了部分依赖

升级后,Feign Client 的 fallback 全部报错:

// 原来的代码
@FeignClient(name = "soa-protocol-control", 
    fallbackFactory = ControlVehicleFeignServiceFallback.class)
public interface ControlVehicleFeignService {
    // ...
}

启动报错:

java.lang.IllegalStateException: 
FallbackFactory must return an instance of the FeignClient interface

我当时又懵了。这又是啥?

原因分析

后来才明白:

  • Hystrix 移除feign.hystrix.FallbackFactory 是 Hystrix 时代的产物
  • 包路径变更:Spring Cloud 2021.x 开始,FallbackFactory 的包路径变了
  • 返回值要求:fallback 必须返回 FeignClient 接口的实例

正确做法

1. 修改导入包

// ❌ 原来的导入(Hystrix 时代)
import feign.hystrix.FallbackFactory;

// ✅ 现在的导入(Resilience4j 时代)
import org.springframework.cloud.openfeign.FallbackFactory;

2. 实现 FallbackFactory

@Slf4j
@Component
public class ControlVehicleFeignServiceFallbackFactory 
    implements FallbackFactory<ControlVehicleFeignService> {

    @Override
    public ControlVehicleFeignService create(Throwable cause) {
        log.error("---控车接口回退异常:{}", cause);
        
        return new ControlVehicleFeignService() {
            @Override
            public BaseResponseVo<Long> executeInstruct(UserControlVehicleDTO dto) {
                return BaseResponseVo.fail(PROTOCOL_CONTROL_ERROR);
            }

            @Override
            public BaseResponseVo<Long> selectCurrentRideUserIdByVin(String vin) {
                return BaseResponseVo.fail(PROTOCOL_CONTROL_ERROR);
            }
            
            // ... 其他方法都返回 fallback 结果
        };
    }
}

3. 使用 FallbackFactory

@FeignClient(
    name = "soa-protocol-control", 
    contextId = "userControlVehicle", 
    fallbackFactory = ControlVehicleFeignServiceFallbackFactory.class  // 注意是 fallbackFactory
)
public interface ControlVehicleFeignService {
    
    @PostMapping("/protocol-control/user/control/vehicle")
    BaseResponseVo<Long> executeInstruct(@RequestBody UserControlVehicleDTO dto);
    
    @GetMapping("/protocol-control/current/ride-user-id")
    BaseResponseVo<Long> selectCurrentRideUserIdByVin(@RequestParam String vin);
    
    // ... 其他接口
}

教训:FallbackFactory 的包路径变了,别用错导入!

坑 3:Ribbon 也不推荐用了?

我以为禁用就完事了

升级后发现 Ribbon 也停更了,启动时各种警告:

WARN: Ribbon is now in maintenance mode. 
Consider using Spring Cloud LoadBalancer instead.

这又是啥?

原因分析

后来才明白:

  • Ribbon 停更:Netflix Ribbon 也进入维护模式
  • 官方推荐:Spring Cloud LoadBalancer 作为替代
  • 配置变更:LoadBalancer 的配置方式和 Ribbon 不一样

正确做法

1. 添加依赖

<!-- Spring Cloud LoadBalancer -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

2. 配置 LoadBalancer

# application.yml
spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false  # 禁用 Ribbon
      cache:
        ttl: 30000  # 缓存过期时间(毫秒)
        capacity: 256  # 缓存容量

3. 自定义负载均衡策略

@Configuration
public class LoadBalancerConfig {
    
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
    
    @Bean
    public ReactorLoadBalancer<ServiceInstance> randomLoadBalancer(
            LoadBalancerClientFactory clientFactory) {
        return new RandomLoadBalancer(
            clientFactory.getLazyProvider("service-name", ServiceInstanceListSupplier.class),
            "service-name"
        );
    }
}

4. 使用 LoadBalancer

@Service
public class MyService {
    
    @Autowired
    private RestTemplate restTemplate;
    
    public String callService(String data) {
        // 使用服务名调用,LoadBalancer 会自动做负载均衡
        String url = "http://service-name/api/" + data;
        return restTemplate.getForObject(url, String.class);
    }
}

教训:Ribbon 已经停更了,赶紧换成 LoadBalancer!

配置对比(Hoxton vs 2021.x)

Hoxton 配置(自动配置)

// 啥都不用配,Hystrix 自动帮你搞定
@EnableHystrix
@EnableFeignClients
@SpringBootApplication
public class Application {
    // ...
}

好处:简单,省事

坏处

  • Hystrix 停更了
  • 性能不如 Resilience4j
  • 配置不灵活

2021.x 配置(手动配置)

// 启用 Resilience4j + OpenFeign + LoadBalancer
@EnableFeignClients
@SpringBootApplication
public class Application {
    // ...
}

// Resilience4j 配置
@Configuration
public class Resilience4jConfig {
    
    @Bean
    public CircuitBreakerConfig circuitBreakerConfig() {
        return CircuitBreakerConfig.custom()
            .failureRateThreshold(50)
            .waitDurationInOpenState(Duration.ofSeconds(10))
            .slidingWindowSize(10)
            .build();
    }
}

好处

  • 官方推荐,持续更新
  • 性能更好
  • 配置更灵活

坏处:配置多了点

我的感受

  • 虽然配置多了,但心里有底
  • Resilience4j 的 API 更现代
  • 出了问题知道从哪查
  • 推荐大家都这么配(虽然麻烦点)

Fallback 和 FallbackFactory 的区别

Fallback:简单场景

适用场景:只需要返回默认值

@FeignClient(
    name = "user-service",
    fallback = UserFeignClientFallback.class  // 直接返回实例
)
public interface UserFeignClient {
    @GetMapping("/user/{id}")
    User getUser(@PathVariable Long id);
}

@Component
public class UserFeignClientFallback implements UserFeignClient {
    @Override
    public User getUser(Long id) {
        return new User(0L, "default", "default@example.com");
    }
}

好处:简单,代码少

坏处:拿不到异常信息

FallbackFactory:复杂场景(推荐)

适用场景:需要记录异常日志、根据异常类型做不同处理

@FeignClient(
    name = "user-service",
    fallbackFactory = UserFeignClientFallbackFactory.class  // 工厂模式
)
public interface UserFeignClient {
    @GetMapping("/user/{id}")
    User getUser(@PathVariable Long id);
}

@Slf4j
@Component
public class UserFeignClientFallbackFactory 
    implements FallbackFactory<UserFeignClient> {
    
    @Override
    public UserFeignClient create(Throwable cause) {
        log.error("Feign 调用失败:{}", cause.getMessage());  // 可以记录日志
        
        return new UserFeignClient() {
            @Override
            public User getUser(Long id) {
                // 根据异常类型做不同处理
                if (cause instanceof ConnectException) {
                    return new User(0L, "network-error", "连接失败");
                } else {
                    return new User(0L, "unknown-error", "未知错误");
                }
            }
        };
    }
}

好处

  • 可以记录异常日志
  • 可以根据异常类型做不同处理
  • 更灵活

坏处:代码多了点

我的建议

  • 简单场景用 Fallback
  • 生产环境推荐用 FallbackFactory(可以记录日志)

验证步骤

1. 检查依赖

# 查看项目依赖树
mvn dependency:tree | Select-String "hystrix|resilience4j|ribbon|loadbalancer"

预期结果

  • 不应该有 spring-cloud-starter-netflix-hystrix
  • 应该有 spring-cloud-starter-circuitbreaker-resilience4j
  • 不应该有 ribbon
  • 应该有 spring-cloud-starter-loadbalancer

2. 启动测试

启动应用,确认没有以下警告:

❌ Hystrix is not compatible with Spring Cloud 2021.x
❌ Ribbon is now in maintenance mode

3. 测试 Fallback

// 手动触发异常,测试 fallback 是否生效
@Test
public void testFallback() {
    // 模拟服务不可用
    String result = feignClient.callService();
    assertEquals("fallback result", result);
}

我整理的一些配置

Resilience4j 推荐配置

# 这些是我实测好用的
resilience4j:
  circuitbreaker:
    instances:
      backendA:
        registerHealthIndicator: true
        slidingWindowSize: 10
        failureRateThreshold: 50
        waitDurationInOpenState: 10000
        permittedNumberOfCallsInHalfOpenState: 5
        automaticTransitionFromOpenToHalfOpenEnabled: true
  timelimiter:
    timeoutDuration: 3s

LoadBalancer 推荐配置

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false
      cache:
        ttl: 30000
        capacity: 256

监控指标

# Resilience4j 的监控指标(要加到 Prometheus 里)
resilience4j.circuitbreaker.states
resilience4j.circuitbreaker.failure.rate
resilience4j.circuitbreaker.slow.call.rate

回滚方案

如果升级后出现问题,可以快速回滚:

  1. 恢复 pom.xml 中的 Spring Boot 和 Spring Cloud 版本
  2. 恢复 Hystrix 依赖
  3. 恢复 Ribbon 依赖
  4. 恢复原来的 Fallback 实现
  5. 重新编译部署

教训:升级前一定要留好退路!

总结

我踩过的坑

  1. 坑 1:以为 Hystrix 还能用 → 启动报不兼容错误
  2. 坑 2:FallbackFactory 导入错误 → 报返回值类型错误
  3. 坑 3:Ribbon 没换成 LoadBalancer → 各种警告

核心要点

  • 必须替换 Hystrix:用 Resilience4j,官方推荐
  • 必须修改 FallbackFactory 导入:从 feign.hystrix 换成 org.springframework.cloud.openfeign
  • 必须替换 Ribbon:用 Spring Cloud LoadBalancer
  • 必须测试 fallback:确保服务降级正常工作

最后说两句

其实也没多难,就是配置多了点。

我刚开始也懵,后来一点点试,总算是搞定了。

肯定有理解不对的地方,欢迎大佬指正。

如果你也遇到类似问题,希望这篇笔记能帮到你。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringMvc配置静态资源访问路径的实现

    SpringMvc配置静态资源访问路径的实现

    本文主要介绍了SpringMvc配置静态资源访问路径的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • Java结合Swing实现龙年祝福语生成工具

    Java结合Swing实现龙年祝福语生成工具

    Swing是一个为Java设计的GUI工具包,属于Java基础类的一部分,本文将使用Java和Swing实现龙年祝福语生成工具,感兴趣的小伙伴可以了解下
    2024-01-01
  • Java实现对华北、华南、华东和华中四个区域的划分

    Java实现对华北、华南、华东和华中四个区域的划分

    在Java中,通过定义枚举类、编写主程序和进行测试,本文详细介绍了如何划分华北、华南、华东和华中四个区域,首先定义枚举类标识区域,然后通过主程序接收用户输入并返回相应区域,最后通过测试用例确保正确性,文章还介绍了甘特图和饼状图的使用
    2024-09-09
  • 使用IDEA搭建SSM框架的详细教程(spring + springMVC +MyBatis)

    使用IDEA搭建SSM框架的详细教程(spring + springMVC +MyBatis)

    这篇文章主要介绍了使用IDEA搭建SSM框架的详细教程 spring + springMVC +MyBatis,本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-05-05
  • Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup

    下面小编就为大家分享一篇Java爬虫实现爬取京东上的手机搜索页面 HttpCliient+Jsoup,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2017-11-11
  • java中break和continue区别及使用场合分析

    java中break和continue区别及使用场合分析

    本文力图通过实例加使用场合详解来引导菜鸟重新认识break和continue语句,需要的朋友可以参考下
    2014-01-01
  • Java使用Tess4J实现图像识别方式

    Java使用Tess4J实现图像识别方式

    这篇文章主要介绍了Java使用Tess4J实现图像识别方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-10-10
  • spring boot整合mybatis利用Mysql实现主键UUID的方法

    spring boot整合mybatis利用Mysql实现主键UUID的方法

    这篇文章主要给大家介绍了关于spring boot整合mybatis利用Mysql实现主键UUID的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧。
    2018-03-03
  • Mac下如何查看已安装的jdk版本及其安装目录

    Mac下如何查看已安装的jdk版本及其安装目录

    这篇文章主要介绍了Mac下如何查看已安装的jdk版本及其安装目录问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • 分模块构建Maven工程的方法步骤

    分模块构建Maven工程的方法步骤

    这篇文章主要介绍了分模块构建Maven工程的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10

最新评论