当前位置: 代码网 > it编程>编程语言>Java > SpringBoot升级后Hystrix没了以及3个替代方案分享

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

2026年04月19日 Java 我要评论
写在前面公司项目要从 spring boot 2.2.x 升级到 2.7,领导让我负责调研。拿到手一看,好家伙,hystrix 停更了?feign 的 fallback 怎么报错了?ribbon 也不

写在前面

公司项目要从 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:确保服务降级正常工作

最后说两句

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

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

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

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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com