最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot升級(jí)后Hystrix沒(méi)了以及3個(gè)替代方案分享

 更新時(shí)間:2026年04月18日 15:34:28   作者:真實(shí)的菜  
這篇文章主要介紹了SpringBoot升級(jí)后Hystrix沒(méi)了以及3個(gè)替代方案分享,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

寫在前面

公司項(xiàng)目要從 Spring Boot 2.2.x 升級(jí)到 2.7,領(lǐng)導(dǎo)讓我負(fù)責(zé)調(diào)研。

拿到手一看,好家伙,Hystrix 停更了?Feign 的 fallback 怎么報(bào)錯(cuò)了?Ribbon 也不推薦用了?

網(wǎng)上的文檔要么太深?yuàn)W,要么太簡(jiǎn)單。沒(méi)辦法,只能自己一點(diǎn)點(diǎn)啃,順便把踩坑經(jīng)歷記下來(lái)。

如果你也是新手,希望這篇筆記能幫到你。

環(huán)境信息

  • 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 停更了,用啥替代?

我當(dāng)時(shí)以為很簡(jiǎn)單

直接升級(jí) Spring Boot 和 Spring Cloud,心想依賴會(huì)自動(dòng)更新…

<!-- 我當(dāng)時(shí)看到這個(gè)配置,心想這不簡(jiǎn)單嗎 -->
<spring-boot.version>2.7.18</spring-boot.version>
<spring-cloud.version>2021.x</spring-cloud.version>

結(jié)果啟動(dòng)失敗:

***************************
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.

我當(dāng)時(shí)就懵了。啥?Hystrix 不兼容?

問(wèn)題根源

后來(lái)查資料才明白:

  1. Hystrix 停更:Netflix Hystrix 從 2020 年開始就進(jìn)入維護(hù)模式,不再更新
  2. Spring Cloud 移除:Spring Cloud 2020.x(Illford)開始移除了對(duì) Hystrix 的支持
  3. 官方推薦:Spring 官方推薦使用 Resilience4j 作為替代方案

好家伙,原來(lái)是時(shí)代的眼淚。

解決方案

用 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:  # 服務(wù)名
        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() {
        // 調(diào)用外部服務(wù)
        return "success";
    }
    
    // fallback 方法
    public String fallback(Exception e) {
        log.error("服務(wù)調(diào)用失敗,執(zhí)行 fallback: {}", e.getMessage());
        return "fallback result";
    }
}

教訓(xùn):Hystrix 已經(jīng)停更了,別再用!官方推薦 Resilience4j!

坑 2:Feign 的 FallbackFactory 報(bào)錯(cuò)了

我只排除了部分依賴

升級(jí)后,F(xiàn)eign Client 的 fallback 全部報(bào)錯(cuò):

// 原來(lái)的代碼
@FeignClient(name = "soa-protocol-control", 
    fallbackFactory = ControlVehicleFeignServiceFallback.class)
public interface ControlVehicleFeignService {
    // ...
}

啟動(dòng)報(bào)錯(cuò):

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

我當(dāng)時(shí)又懵了。這又是啥?

原因分析

后來(lái)才明白:

  • Hystrix 移除feign.hystrix.FallbackFactory 是 Hystrix 時(shí)代的產(chǎn)物
  • 包路徑變更:Spring Cloud 2021.x 開始,F(xiàn)allbackFactory 的包路徑變了
  • 返回值要求:fallback 必須返回 FeignClient 接口的實(shí)例

正確做法

1. 修改導(dǎo)入包

// ? 原來(lái)的導(dǎo)入(Hystrix 時(shí)代)
import feign.hystrix.FallbackFactory;

// ? 現(xiàn)在的導(dǎo)入(Resilience4j 時(shí)代)
import org.springframework.cloud.openfeign.FallbackFactory;

2. 實(shí)現(xiàn) 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 結(jié)果
        };
    }
}

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);
    
    // ... 其他接口
}

教訓(xùn):FallbackFactory 的包路徑變了,別用錯(cuò)導(dǎo)入!

坑 3:Ribbon 也不推薦用了?

我以為禁用就完事了

升級(jí)后發(fā)現(xiàn) Ribbon 也停更了,啟動(dòng)時(shí)各種警告:

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

這又是啥?

原因分析

后來(lái)才明白:

  • Ribbon 停更:Netflix Ribbon 也進(jìn)入維護(hù)模式
  • 官方推薦: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  # 緩存過(guò)期時(shí)間(毫秒)
        capacity: 256  # 緩存容量

3. 自定義負(fù)載均衡策略

@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) {
        // 使用服務(wù)名調(diào)用,LoadBalancer 會(huì)自動(dòng)做負(fù)載均衡
        String url = "http://service-name/api/" + data;
        return restTemplate.getForObject(url, String.class);
    }
}

教訓(xùn):Ribbon 已經(jīng)停更了,趕緊換成 LoadBalancer!

配置對(duì)比(Hoxton vs 2021.x)

Hoxton 配置(自動(dòng)配置)

// 啥都不用配,Hystrix 自動(dòng)幫你搞定
@EnableHystrix
@EnableFeignClients
@SpringBootApplication
public class Application {
    // ...
}

好處:簡(jiǎn)單,省事

壞處

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

2021.x 配置(手動(dòng)配置)

// 啟用 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();
    }
}

好處

  • 官方推薦,持續(xù)更新
  • 性能更好
  • 配置更靈活

壞處:配置多了點(diǎn)

我的感受

  • 雖然配置多了,但心里有底
  • Resilience4j 的 API 更現(xiàn)代
  • 出了問(wèn)題知道從哪查
  • 推薦大家都這么配(雖然麻煩點(diǎn))

Fallback 和 FallbackFactory 的區(qū)別

Fallback:簡(jiǎn)單場(chǎng)景

適用場(chǎng)景:只需要返回默認(rèn)值

@FeignClient(
    name = "user-service",
    fallback = UserFeignClientFallback.class  // 直接返回實(shí)例
)
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");
    }
}

好處:簡(jiǎn)單,代碼少

壞處:拿不到異常信息

FallbackFactory:復(fù)雜場(chǎng)景(推薦)

適用場(chǎng)景:需要記錄異常日志、根據(jù)異常類型做不同處理

@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 調(diào)用失?。簕}", cause.getMessage());  // 可以記錄日志
        
        return new UserFeignClient() {
            @Override
            public User getUser(Long id) {
                // 根據(jù)異常類型做不同處理
                if (cause instanceof ConnectException) {
                    return new User(0L, "network-error", "連接失敗");
                } else {
                    return new User(0L, "unknown-error", "未知錯(cuò)誤");
                }
            }
        };
    }
}

好處

  • 可以記錄異常日志
  • 可以根據(jù)異常類型做不同處理
  • 更靈活

壞處:代碼多了點(diǎn)

我的建議

  • 簡(jiǎn)單場(chǎng)景用 Fallback
  • 生產(chǎn)環(huán)境推薦用 FallbackFactory(可以記錄日志)

驗(yàn)證步驟

1. 檢查依賴

# 查看項(xiàng)目依賴樹
mvn dependency:tree | Select-String "hystrix|resilience4j|ribbon|loadbalancer"

預(yù)期結(jié)果

  • 不應(yīng)該有 spring-cloud-starter-netflix-hystrix
  • 應(yīng)該有 spring-cloud-starter-circuitbreaker-resilience4j
  • 不應(yīng)該有 ribbon
  • 應(yīng)該有 spring-cloud-starter-loadbalancer

2. 啟動(dòng)測(cè)試

啟動(dòng)應(yīng)用,確認(rèn)沒(méi)有以下警告:

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

3. 測(cè)試 Fallback

// 手動(dòng)觸發(fā)異常,測(cè)試 fallback 是否生效
@Test
public void testFallback() {
    // 模擬服務(wù)不可用
    String result = feignClient.callService();
    assertEquals("fallback result", result);
}

我整理的一些配置

Resilience4j 推薦配置

# 這些是我實(shí)測(cè)好用的
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

監(jiān)控指標(biāo)

# Resilience4j 的監(jiān)控指標(biāo)(要加到 Prometheus 里)
resilience4j.circuitbreaker.states
resilience4j.circuitbreaker.failure.rate
resilience4j.circuitbreaker.slow.call.rate

回滾方案

如果升級(jí)后出現(xiàn)問(wèn)題,可以快速回滾:

  1. 恢復(fù) pom.xml 中的 Spring Boot 和 Spring Cloud 版本
  2. 恢復(fù) Hystrix 依賴
  3. 恢復(fù) Ribbon 依賴
  4. 恢復(fù)原來(lái)的 Fallback 實(shí)現(xiàn)
  5. 重新編譯部署

教訓(xùn):升級(jí)前一定要留好退路!

總結(jié)

我踩過(guò)的坑

  1. 坑 1:以為 Hystrix 還能用 → 啟動(dòng)報(bào)不兼容錯(cuò)誤
  2. 坑 2:FallbackFactory 導(dǎo)入錯(cuò)誤 → 報(bào)返回值類型錯(cuò)誤
  3. 坑 3:Ribbon 沒(méi)換成 LoadBalancer → 各種警告

核心要點(diǎn)

  • 必須替換 Hystrix:用 Resilience4j,官方推薦
  • 必須修改 FallbackFactory 導(dǎo)入:從 feign.hystrix 換成 org.springframework.cloud.openfeign
  • 必須替換 Ribbon:用 Spring Cloud LoadBalancer
  • 必須測(cè)試 fallback:確保服務(wù)降級(jí)正常工作

最后說(shuō)兩句

其實(shí)也沒(méi)多難,就是配置多了點(diǎn)。

我剛開始也懵,后來(lái)一點(diǎn)點(diǎn)試,總算是搞定了。

肯定有理解不對(duì)的地方,歡迎大佬指正。

如果你也遇到類似問(wèn)題,希望這篇筆記能幫到你。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Maven編譯遇到Process terminated問(wèn)題(四種情況全部解決)

    Maven編譯遇到Process terminated問(wèn)題(四種情況全部解決)

    這篇文章主要介紹了Maven編譯遇到Process terminated問(wèn)題(四種情況全部解決),具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Spring解讀@Component和@Configuration的區(qū)別以及源碼分析

    Spring解讀@Component和@Configuration的區(qū)別以及源碼分析

    通過(guò)實(shí)例分析@Component和@Configuration注解的區(qū)別,核心在于@Configuration會(huì)通過(guò)CGLIB代理確保Bean的單例,而@Component不會(huì),在Spring容器中,使用@Configuration注解的類會(huì)被CGLIB增強(qiáng),保證了即使在同一個(gè)類中多次調(diào)用@Bean方法
    2024-10-10
  • springboot Jpa多數(shù)據(jù)源(不同庫(kù))配置過(guò)程

    springboot Jpa多數(shù)據(jù)源(不同庫(kù))配置過(guò)程

    這篇文章主要介紹了springboot Jpa多數(shù)據(jù)源(不同庫(kù))配置過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • SpringBoot使用Spring?Cache高效處理緩存數(shù)據(jù)

    SpringBoot使用Spring?Cache高效處理緩存數(shù)據(jù)

    Spring?Cache是一個(gè)框架,只要簡(jiǎn)單加一個(gè)注解,就能實(shí)現(xiàn)緩存功能,本文主要介紹了SpringBoot使用Spring?Cache高效處理緩存數(shù)據(jù),感興趣的可以了解一下
    2023-11-11
  • Idea 2020.2安裝MyBatis Log Plugin 不可用的解決方法

    Idea 2020.2安裝MyBatis Log Plugin 不可用的解決方法

    小編在使用時(shí)發(fā)現(xiàn)Idea 2020.2 MyBatis Log Plugin 收費(fèi)了,這個(gè)可以替代用,小編特此把解決方案分享到腳本之家平臺(tái)供大家參考,感興趣的朋友一起看看吧
    2020-11-11
  • Java中用戶線程與守護(hù)線程的使用區(qū)別

    Java中用戶線程與守護(hù)線程的使用區(qū)別

    這篇文章主要介紹了Java中用戶線程與守護(hù)線程的使用區(qū)別,Java語(yǔ)言中無(wú)論是線程還是線程池,默認(rèn)都是用戶線程,因此用戶線程也被成為普通線程,下文關(guān)于其與守護(hù)線程的區(qū)別詳情,需要的小伙伴可以參考一下
    2022-05-05
  • 詳解在java中進(jìn)行日期時(shí)間比較的4種方法

    詳解在java中進(jìn)行日期時(shí)間比較的4種方法

    這篇文章主要介紹了詳解在java中進(jìn)行日期時(shí)間比較的4種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • Java中ArrayList與順序表示例詳解

    Java中ArrayList與順序表示例詳解

    順序表是在計(jì)算機(jī)內(nèi)存中以數(shù)組的形式保存的線性表,是指用一組地址連續(xù)的存儲(chǔ)單元依次存儲(chǔ)數(shù)據(jù)元素的線性結(jié)構(gòu),這篇文章主要介紹了Java中ArrayList與順序表的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2025-12-12
  • El表達(dá)式使用問(wèn)題javax.el.ELException:Failed to parse the expression的解決方式

    El表達(dá)式使用問(wèn)題javax.el.ELException:Failed to parse the expression

    今天小編就為大家分享一篇關(guān)于Jsp El表達(dá)式使用問(wèn)題javax.el.ELException:Failed to parse the expression的解決方式,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • java實(shí)現(xiàn)切圖并且判斷圖片是不是純色/彩色圖片

    java實(shí)現(xiàn)切圖并且判斷圖片是不是純色/彩色圖片

    本篇文章主要介紹了java實(shí)現(xiàn)切圖并且判斷圖片是否是純色/彩色圖片,具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-08-08

最新評(píng)論

潼关县| 大荔县| 佛冈县| 塔城市| 南郑县| 西昌市| 大洼县| 高要市| 南昌市| 新疆| 佳木斯市| 洪洞县| 天峨县| 双鸭山市| 奉节县| 福建省| 阳原县| 内乡县| 辽宁省| 措勤县| 池州市| 颍上县| 武定县| 阳江市| 新巴尔虎右旗| 湘阴县| 东乌| 红安县| 玉田县| 高尔夫| 安溪县| 长岭县| 阿拉善右旗| 伊川县| 贡嘎县| 偏关县| 家居| 库车县| 辽源市| 囊谦县| 新疆|