Spring Boot 升级后,Hystrix 没了?我找到了这 3 个替代方案
Spring Boot 升级后Hystrix 没了我找到了这 3 个替代方案写在前面公司项目要从 Spring Boot 2.2.x 升级到 2.7领导让我负责调研。拿到手一看好家伙Hystrix 停更了Feign 的 fallback 怎么报错了Ribbon 也不推荐用了网上的文档要么太深奥要么太简单。没办法只能自己一点点啃顺便把踩坑经历记下来。如果你也是新手希望这篇笔记能帮到你。环境信息Spring Boot: 2.2.x → 2.7.18Spring Cloud: Hoxton.SR9 → 2021.xHystrix: 1.5.x停更→ Resilience4j 1.7.xRibbon: 2.x停更→ Spring Cloud LoadBalancerOpenFeign: 2.2.x → 3.1.x坑 1Hystrix 停更了用啥替代❌ 我当时以为很简单直接升级 Spring Boot 和 Spring Cloud心想依赖会自动更新…!-- 我当时看到这个配置心想这不简单吗 --spring-boot.version2.7.18/spring-boot.versionspring-cloud.version2021.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 不兼容 问题根源后来查资料才明白Hystrix 停更Netflix Hystrix 从 2020 年开始就进入维护模式不再更新Spring Cloud 移除Spring Cloud 2020.xIllford开始移除了对 Hystrix 的支持官方推荐Spring 官方推荐使用 Resilience4j 作为替代方案好家伙原来是时代的眼泪。✅ 解决方案用 Resilience4j 替代 Hystrix!-- 移除 Hystrix 依赖 --!-- dependency groupIdorg.springframework.cloud/groupId artifactIdspring-cloud-starter-netflix-hystrix/artifactId /dependency --!-- 添加 Resilience4j 依赖 --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-circuitbreaker-resilience4j/artifactId/dependency配置 Resilience4j# application.ymlresilience4j:circuitbreaker:instances:backendA:# 服务名registerHealthIndicator:trueslidingWindowSize:10failureRateThreshold:50waitDurationInOpenState:10000permittedNumberOfCallsInHalfOpenState:5automaticTransitionFromOpenToHalfOpenEnabled:truetimeout:timeout:3scancelRunningFuture:false使用方式ServicepublicclassMyService{CircuitBreaker(namebackendA,fallbackMethodfallback)publicStringcallExternalService(){// 调用外部服务returnsuccess;}// fallback 方法publicStringfallback(Exceptione){log.error(服务调用失败执行 fallback: {},e.getMessage());returnfallback result;}}教训Hystrix 已经停更了别再用官方推荐 Resilience4j坑 2Feign 的 FallbackFactory 报错了❌ 我只排除了部分依赖升级后Feign Client 的 fallback 全部报错// 原来的代码FeignClient(namesoa-protocol-control,fallbackFactoryControlVehicleFeignServiceFallback.class)publicinterfaceControlVehicleFeignService{// ...}启动报错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 时代importfeign.hystrix.FallbackFactory;// ✅ 现在的导入Resilience4j 时代importorg.springframework.cloud.openfeign.FallbackFactory;2. 实现 FallbackFactorySlf4jComponentpublicclassControlVehicleFeignServiceFallbackFactoryimplementsFallbackFactoryControlVehicleFeignService{OverridepublicControlVehicleFeignServicecreate(Throwablecause){log.error(---控车接口回退异常{},cause);returnnewControlVehicleFeignService(){OverridepublicBaseResponseVoLongexecuteInstruct(UserControlVehicleDTOdto){returnBaseResponseVo.fail(PROTOCOL_CONTROL_ERROR);}OverridepublicBaseResponseVoLongselectCurrentRideUserIdByVin(Stringvin){returnBaseResponseVo.fail(PROTOCOL_CONTROL_ERROR);}// ... 其他方法都返回 fallback 结果};}}3. 使用 FallbackFactoryFeignClient(namesoa-protocol-control,contextIduserControlVehicle,fallbackFactoryControlVehicleFeignServiceFallbackFactory.class// 注意是 fallbackFactory)publicinterfaceControlVehicleFeignService{PostMapping(/protocol-control/user/control/vehicle)BaseResponseVoLongexecuteInstruct(RequestBodyUserControlVehicleDTOdto);GetMapping(/protocol-control/current/ride-user-id)BaseResponseVoLongselectCurrentRideUserIdByVin(RequestParamStringvin);// ... 其他接口}教训FallbackFactory 的包路径变了别用错导入坑 3Ribbon 也不推荐用了❌ 我以为禁用就完事了升级后发现 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 --dependencygroupIdorg.springframework.cloud/groupIdartifactIdspring-cloud-starter-loadbalancer/artifactId/dependency2. 配置 LoadBalancer# application.ymlspring:cloud:loadbalancer:ribbon:enabled:false# 禁用 Ribboncache:ttl:30000# 缓存过期时间毫秒capacity:256# 缓存容量3. 自定义负载均衡策略ConfigurationpublicclassLoadBalancerConfig{BeanLoadBalancedpublicRestTemplaterestTemplate(){returnnewRestTemplate();}BeanpublicReactorLoadBalancerServiceInstancerandomLoadBalancer(LoadBalancerClientFactoryclientFactory){returnnewRandomLoadBalancer(clientFactory.getLazyProvider(service-name,ServiceInstanceListSupplier.class),service-name);}}4. 使用 LoadBalancerServicepublicclassMyService{AutowiredprivateRestTemplaterestTemplate;publicStringcallService(Stringdata){// 使用服务名调用LoadBalancer 会自动做负载均衡Stringurlhttp://service-name/api/data;returnrestTemplate.getForObject(url,String.class);}}教训Ribbon 已经停更了赶紧换成 LoadBalancer配置对比Hoxton vs 2021.xHoxton 配置自动配置// 啥都不用配Hystrix 自动帮你搞定EnableHystrixEnableFeignClientsSpringBootApplicationpublicclassApplication{// ...}好处简单省事坏处Hystrix 停更了性能不如 Resilience4j配置不灵活2021.x 配置手动配置// 启用 Resilience4j OpenFeign LoadBalancerEnableFeignClientsSpringBootApplicationpublicclassApplication{// ...}// Resilience4j 配置ConfigurationpublicclassResilience4jConfig{BeanpublicCircuitBreakerConfigcircuitBreakerConfig(){returnCircuitBreakerConfig.custom().failureRateThreshold(50).waitDurationInOpenState(Duration.ofSeconds(10)).slidingWindowSize(10).build();}}好处官方推荐持续更新性能更好配置更灵活坏处配置多了点我的感受虽然配置多了但心里有底Resilience4j 的 API 更现代出了问题知道从哪查推荐大家都这么配虽然麻烦点Fallback 和 FallbackFactory 的区别Fallback简单场景适用场景只需要返回默认值FeignClient(nameuser-service,fallbackUserFeignClientFallback.class// 直接返回实例)publicinterfaceUserFeignClient{GetMapping(/user/{id})UsergetUser(PathVariableLongid);}ComponentpublicclassUserFeignClientFallbackimplementsUserFeignClient{OverridepublicUsergetUser(Longid){returnnewUser(0L,default,defaultexample.com);}}好处简单代码少坏处拿不到异常信息FallbackFactory复杂场景推荐适用场景需要记录异常日志、根据异常类型做不同处理FeignClient(nameuser-service,fallbackFactoryUserFeignClientFallbackFactory.class// 工厂模式)publicinterfaceUserFeignClient{GetMapping(/user/{id})UsergetUser(PathVariableLongid);}Slf4jComponentpublicclassUserFeignClientFallbackFactoryimplementsFallbackFactoryUserFeignClient{OverridepublicUserFeignClientcreate(Throwablecause){log.error(Feign 调用失败{},cause.getMessage());// 可以记录日志returnnewUserFeignClient(){OverridepublicUsergetUser(Longid){// 根据异常类型做不同处理if(causeinstanceofConnectException){returnnewUser(0L,network-error,连接失败);}else{returnnewUser(0L,unknown-error,未知错误);}}};}}好处可以记录异常日志可以根据异常类型做不同处理更灵活坏处代码多了点我的建议简单场景用 Fallback生产环境推荐用 FallbackFactory可以记录日志验证步骤1. 检查依赖# 查看项目依赖树mvn dependency:tree|Select-Stringhystrix|resilience4j|ribbon|loadbalancer预期结果不应该有spring-cloud-starter-netflix-hystrix应该有spring-cloud-starter-circuitbreaker-resilience4j不应该有ribbon应该有spring-cloud-starter-loadbalancer2. 启动测试启动应用确认没有以下警告❌ Hystrix is not compatible with Spring Cloud 2021.x ❌ Ribbon is now in maintenance mode3. 测试 Fallback// 手动触发异常测试 fallback 是否生效TestpublicvoidtestFallback(){// 模拟服务不可用StringresultfeignClient.callService();assertEquals(fallback result,result);}我整理的一些配置Resilience4j 推荐配置# 这些是我实测好用的resilience4j:circuitbreaker:instances:backendA:registerHealthIndicator:trueslidingWindowSize:10failureRateThreshold:50waitDurationInOpenState:10000permittedNumberOfCallsInHalfOpenState:5automaticTransitionFromOpenToHalfOpenEnabled:truetimelimiter:timeoutDuration:3sLoadBalancer 推荐配置spring:cloud:loadbalancer:ribbon:enabled:falsecache:ttl:30000capacity:256监控指标# Resilience4j 的监控指标要加到 Prometheus 里resilience4j.circuitbreaker.states resilience4j.circuitbreaker.failure.rate resilience4j.circuitbreaker.slow.call.rate回滚方案如果升级后出现问题可以快速回滚恢复pom.xml中的 Spring Boot 和 Spring Cloud 版本恢复 Hystrix 依赖恢复 Ribbon 依赖恢复原来的 Fallback 实现重新编译部署教训升级前一定要留好退路总结我踩过的坑坑 1以为 Hystrix 还能用 → 启动报不兼容错误坑 2FallbackFactory 导入错误 → 报返回值类型错误坑 3Ribbon 没换成 LoadBalancer → 各种警告核心要点必须替换 Hystrix用 Resilience4j官方推荐必须修改 FallbackFactory 导入从feign.hystrix换成org.springframework.cloud.openfeign必须替换 Ribbon用 Spring Cloud LoadBalancer必须测试 fallback确保服务降级正常工作最后说两句其实也没多难就是配置多了点。我刚开始也懵后来一点点试总算是搞定了。肯定有理解不对的地方欢迎大佬指正。如果你也遇到类似问题希望这篇笔记能帮到你。