SpringCloud系列-整合Hystrix的兩種方式

  • 2019 年 10 月 17 日
  • 筆記

Hystrix [hɪst’rɪks],中文含義是豪豬,因其背上長滿棘刺,從而擁有了自我保護的能力。本文所說的Hystrix是Netflix開源的一款容錯框架,同樣具有自我保護能力。

本文目錄

一、Hystrix簡介二、Hystrix的設計原則三、Hystrix的工作原理四、Ribbon中使用熔斷器五、Feign中使用熔斷器六、踩到的坑

一、Hystrix簡介

Hystrix是由Netflix開源的一個延遲和容錯庫,用於隔離訪問遠程系統、服務或者第三方庫,防止級聯失敗,從而提升系統的可用性、容錯性與局部應用的彈性,是一個實現了超時機制和斷路器模式的工具類庫。

二、Hystrix的設計原則

  • 防止任何單獨的依賴耗盡資源(執行緒)
    過載立即切斷並快速失敗,防止排隊
  • 儘可能提供回退以保護用戶免受故障
  • 使用隔離技術(例如隔板,泳道和斷路器模式)來限制任何一個依賴的影響
  • 通過近實時的指標,監控和告警,確保故障被及時發現
  • 通過動態修改配置屬性,確保故障及時恢復
  • 防止整個依賴客戶端執行失敗,而不僅僅是網路通訊

三、Hystrix的工作原理

  • 使用命令模式將所有對外部服務(或依賴關係)的調用包裝在HystrixCommand或HystrixObservableCommand對象中,並將該對象放在單獨的執行緒中執行。
  • 每個依賴都維護著一個執行緒池(或訊號量),執行緒池被耗盡則拒絕請求(而不是讓請求排隊)。
  • 記錄請求成功,失敗,超時和執行緒拒絕。
  • 服務錯誤百分比超過了閾值,熔斷器開關自動打開,一段時間內停止對該服務的所有請求。
  • 請求失敗,被拒絕,超時或熔斷時執行降級邏輯。
  • 近實時地監控指標和配置的修改。

當使用Hystrix封裝每個基礎依賴項時,每個依賴項彼此隔離,受到延遲時發生飽和的資源的限制,並包含回退邏輯,該邏輯決定了在依賴項中發生任何類型的故障時做出什麼響應。

四、Ribbon中使用熔斷器

按照下面步驟改造之前的項目spring-cloud-consumer-ribbon

  1. pom.xml引入jar包
<!-- 整合hystrix -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
  1. 啟動類上添加@EnableHystrix註解

在啟動類上添加@EnableHystrix註解開啟Hystrix的熔斷器功能,改造後啟動類如下:

@EnableHystrix //在啟動類上添加@EnableHystrix註解開啟Hystrix的熔斷器功能。
@EnableEurekaClient
@SpringBootApplication
public class RibbonConsumerApplication {

    //當添加@LoadBalanced註解,就代表啟動Ribbon,進行負載均衡
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(RibbonConsumerApplication.class, args);
    }

}
  1. 添加HystrixConsumerController

在需要有熔斷機制的方法上添加 @HystrixCommand,屬性fallbackMethod是熔斷時返回的方法,編寫完成後HystrixConsumerController.java程式碼如下:

/**
 * 消費者
 */

@Slf4j
@RestController
@RequestMapping("/hystrix/consumer")
public class HystrixConsumerController {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 調用 user微服務
     */

    @HystrixCommand(fallbackMethod = "getDefaultUser")
    @GetMapping("getUser")
    public String getUser(Integer id) {
        String url = "http://user-service/provider/getUser?id=" + id;
        return restTemplate.getForObject(url, String.class);
    }

    public String getDefaultUser(Integer id) {
        System.out.println("熔斷,默認回調函數");
        return "{"id":-1,"name":"熔斷用戶","password":"123456"}";
    }
}
  1. 開始測試

程式碼編寫之後,按順序啟動spring-cloud-eureka、spring-cloud-user-service和spring-cloud-consumer-ribbon,此時打開瀏覽器訪問http://localhost:8082/hystrix/consumer/getUser?id=2,服務正常,截圖如下:


服務正常截圖

然後停服務spring-cloud-user-service,再次訪問訪問http://localhost:8082/hystrix/consumer/getUser?id=2,此時會觸發熔斷,截圖如下:


觸發熔斷後截圖

五、Feign中使用熔斷器

Feign在整合到Spring Cloud時已經自帶了hystrix模組,所以pom.xml中不需要額外引入feign依賴。

新建一個spring boot項目spring-cloud-consumer-fegin-hystrix,按照下面步驟操作。

  1. application.yml中開啟熔斷器
server:
  port: 8082 #服務埠
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9001/eureka/
spring:
  application:
    name: fegin-hystrix-consumer

feign:
      hystrix:
        # feign熔斷器開關
        enabled: true
  1. 新建一個FeignClient介面

新建一個FeignClient介面UserFeginService並指定fallback,程式碼如下:

//表示"user-service"的服務,指定fallback
@FeignClient(value = "user-service", fallback = UserFeginFailBackImpl.class)
public interface UserFeginService {

    @RequestMapping(value = "/provider/getUser")
    public String getUser(@RequestParam("id") Integer id);
}

@FeignClient註解參數說明:

  • name:指定FeignClient的名稱,如果項目使用了Ribbon,name屬性會作為微服務的名稱,用於服務發現。

  • fallback: 定義容錯的處理類,當調用遠程介面失敗或超時時,會調用對應介面的容錯邏輯,fallback指定的類必須實現@FeignClient標記的介面。

  • fallbackFactory: 工廠類,用於生成fallback類示例,通過這個屬性我們可以實現每個介面通用的容錯邏輯,減少重複的程式碼

  • path: 定義當前FeignClient的統一前綴,類似於註解到類上的@RequestMapping的功能

  1. 添加熔斷處理類UserFeginFailBackImpl

程式碼如下:

@Slf4j
@Component
public class UserFeginFailBackImpl implements UserFeginService {

    @Override
    public String getUser(Integer id) {
        log.info("熔斷,默認回調函數");
        return "{"id":-1,"name":"熔斷用戶","msg":"請求異常,返回熔斷用戶!"}";
    }
}
  1. 添加Controller

添加FeginHystrixController,用於調用user-service,程式碼如下:

@RestController
@RequestMapping("/hystrix/consumer")
public class FeginHystrixController {

    @Autowired
    private UserFeginService userFeginService;

    @GetMapping("/getUser")
    public String getUser(Integer id) {
        return userFeginService.getUser(id);
    }
}

5 開始測試

程式碼編寫之後,按順序啟動spring-cloud-eureka、spring-cloud-user-service和spring-cloud-consumer-fegin-hystrix,此時打開瀏覽器訪問http://localhost:8082/hystrix/consumer/getUser?id=2,服務正常,截圖如下:


服務正常截圖

然後停服務spring-cloud-user-service,再次訪問訪問http://localhost:8082/hystrix/consumer/getUser?id=2,此時會觸發熔斷,截圖如下:


觸發熔斷後截圖

六、踩到的坑

  1. hystrix的異常fallback method wasn’t found

出現這個異常是因為指定的備用方法和原方法的參數個數或類型不同造成的,所以需要統一參數的類型和個數。

到此SpringCloud兩種方式整合Hystrix的功能已經全部實現,有問題歡迎留言溝通哦!

完整源碼地址: https://github.com/suisui2019/springboot-study

推薦閱讀

1.SpringCloud系列-利用Feign實現聲明式服務調用)
2.手把手帶你利用Ribbon實現客戶端的負載均》
3.SpringCloud搭建註冊中心與服務註冊
4.Spring Boot配置過濾器的兩種方式!
5.編碼神器Lombok,學會後開發效率至少提高一倍!


限時領取免費Java相關資料,涵蓋了Java、Redis、MongoDB、MySQL、Zookeeper、Spring Cloud、Dubbo/Kafka、Hadoop、Hbase、Flink等高並發分散式、大數據、機器學習等技術。
關注下方公眾號即可免費領取:

Java碎碎念公眾號Java碎碎念公眾號