SpringCloud之Hystrix(斷路器)

分佈式系統面臨的問題
#### 扇出

多個微服務互相調用的時候,如果A調用B、C,而B、C又繼續調用其他微服務,這就是扇出(像一把扇子一樣慢慢打開

#### 服務雪崩
- 刪除過程中,如果某一個環節的服務出現故障或連接超時,就會導致前面的服務佔用越來越多的資源,進而引起系統崩潰,就是“雪崩效應”。

- 對於高流量的應用來說,單一的後端依賴會導致服務器所有的資源都在幾秒鐘內飽和。比失敗更糟糕的是,這些應用程序還可能導致服務之間的延遲增加,備份隊列,線程和其他系統資源緊張,導致整個系統發生更多的級聯故障。這些都表示需要==對故障和延遲進行隔離和管理==,以便單個依賴關係的失敗,不能取消整個應用程序或系統

Hystrix 斷路器

Hystrix是一個用於處理分佈式系統的延遲和容錯的開源庫,在分佈式系統裏,許多依賴不可避免的會調用失敗,比如超時,異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免級聯故障,以提高分佈式系統的彈性;

"斷路器"本身是一種開關裝置,當某個服務單元發生故障之後,通過斷路器的故障監控(類似熔斷保險絲),向調用方返回一個符合預期的,可處理的備選響應(FallBack),而不是長時間的等待或者拋出調用方無法處理的異常,這樣就保證了服務調用方的線程不會被長時間,不必要地佔用,從而避免了故障在分佈式系統中的蔓延,乃至雪崩

文檔:https://github.com/Netflix/Hystrix/wiki/How-To-Use

服務熔斷
熔斷機制是應對雪崩效應的一種微服務鏈路保護機制;
當扇出鏈路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速返回"錯誤"的響應信息;當檢測到該節點微服務調用正常後恢復調用鏈路;

##### 熔斷案例
1. 構建一個新的provider module(如複製8001module)
2. pom.xml加入hystrix依賴(一定要配合Eureka)

新建microservicecloud-provider-dept-hystrix-8001

// 參考 microservicecloud-provider-dept-8001

// pom.xml
<!-- hystrix -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>

application.xml中配置端口和Eureka信息(必配)和其他框架的配置信息(可選,如mybatis)

// application.yml
eureka:
  client: # 客戶端註冊進eureka服務列表內
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
  instance:
    instance-id: microservicecloud-dept8001-hystrix # 自定義hystrix相關的服務名稱信息
    prefer-ip-address: true  # 訪問路徑可以顯示IP地址

controller類中,在需要配置Fallback的方法上加入@HystrixCommand(fallbackMethod = "XXX")註解,XXX爲FallBack方法名本例中作爲測試所以拋出了異常

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    @Autowired
    private DiscoveryClient client;

    @RequestMapping(value="/dept/get/{id}",method=RequestMethod.GET)
    // 一旦調用服務方法失敗並拋出錯誤信息後,會自動調用@HystrixCommand標註好的fallbackMethod調用類中的指定方法
    @HystrixCommand(fallbackMethod="processHystrix_Get")  
    public Dept get(@PathVariable("id") Long id) {
        Dept dept = this.deptService.get(id);
        if(null == dept) {
            throw new RuntimeException("該ID:"+id+"沒有對應的信息");
        }
        return dept;
    }

    public Dept processHystrix_Get(@PathVariable("id") Long id) {
        return new Dept().setDeptno(id).setDname("該ID:"+id+"沒有對應的信息,null -- @HystrixCommand")
                .setDb_source("no this database in MySQL");
    }
}

// 修改主啓動類DeptProvider8001_Hystrix_App並添加新註解@EnableCircuitBreaker

@SpringBootApplication
@EnableEurekaClient // 本服務啓動後,自動註冊進eureka服務中
@EnableDiscoveryClient // 服務發現
@EnableCircuitBreaker // 對Hystrix熔斷機制的支持
public class DeptProvider8001_Hystrix_App {

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

// 測試訪問:// http://localhost:8082/consumer/dept/get/112


服務降級
服務降級:整體資源快不夠了,忍痛將某些服務先關掉,待渡過難關,再開啓回來;
服務降級處理是在客戶端實現完成的,與服務端沒有關係;

當某個服務熔斷之後,服務器將不再被調用,此時客戶端可以自己準備一個本地的fallback回調,返回一個缺省值;

##### 爲什麼要解耦

如果按照上面的熔斷案例來做的話,Controller下的每個方法,都要給其編寫一個FallBack方法,當方法慢慢變多,就會造成代碼膨脹,一個是增加編寫的工作量,另外一個也會增大維護的難度,代碼的耦合度也會高,是十分不合理的,所以要將其解耦

##### 解耦思路

因爲服務端的是通過實現接口訪問服務端的,如果在父接口上實現了FallBack方法,通過這樣一種方式去維護起來就能實現解耦,也順便完成了降級的機制

##### 解耦&降級案例

1. 在api模塊中新建實現了FallbackFactory<T>接口的類,其中泛型T就是我們需要維護其FallBack的接口方法,並實現其create方法,在create方法中返回實現了T的對象,使用匿名內部類實現T。==注意:這個類一定要加@Component註解!!這個類一定要加@Component註解!!這個類一定要加@Component註解!!==

// 修改microservicecloud-api工程
// 根據已有的DeptClientService接口,新建一個實現了FallbackFactory接口的類DeptClientServiceFallbackFactory

@Component  // 不要忘記添加
public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {

    @Override
    public DeptClientService create(Throwable arg0) {

        return new DeptClientService() {

            @Override
            public Dept get(long id) {
                return new Dept().setDeptno(id).setDname("該ID:"+id+"沒有對應的信息,Consumer客戶端提供的降級信息,此刻服務Provider已經關閉")
                        .setDb_source("no this database in MySQL");
            }

            @Override
            public List<Dept> list() {

                return null;
            }

            @Override
            public boolean add(Dept dept) {

                return false;
            }
        };
    }
}

2. 修改步驟1中傳入的泛型T接口,添加@FeignClient(fallbackFactory = T.class)註解
// 修改microservicecloud-api工程, DeptClientService接口

// 在註解@FeignClient中添加 fallbackFactory 屬性值

@FeignClient(value="MICROSERVICECLOUD-DEPT",
            fallbackFactory=DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

    @RequestMapping(value="/dept/get/{id}", method= RequestMethod.GET)
    public Dept get(@PathVariable("id") long id);

    @RequestMapping(value="/dept/list", method= RequestMethod.GET)
    public List<Dept> list();

    @RequestMapping(value="/dept/add", method= RequestMethod.POST)
    public boolean add(Dept dept);
}

// mvn clean,// mvn install

3. 修改consumer feign模塊的application.xml文件,開啓hystrix(注:在IDEA中可能沒有代碼提示,開啓的true也沒有正常高亮,但好像不需要做額外操作也不影響結果)

// 修改microservicecloud-consumer-dept-feign 工程

// application.yml

feign:
  hystrix:
    enabled: true
// 測試訪問:// http://localhost:8082/consumer/dept/get/1

// 然後手動關閉工程:microservicecloud-provider-dept-8001


HystrixDashboard服務監控

介紹:SpringCloud對Hystrix Dashboard進行了整合,可以對通過Hystrix發起的請求進行準實時統計,並以報表和圖形的形式展示給用戶(包括每秒執行多少次請求成功和失敗等)

##### 配置案例

新建工程microservicecloud-consumer-hystrix-dashboard

1. 新建HystrixDashboard模塊,pom.xml文件加入HystrixDashboard依賴,其他依賴包括Feign,Ribbon,Eureka(可參考80模塊的依賴)

// pom.xml
<!-- hystrix和hystrix-dashboard 相關 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
</dependency>

2. application.yml文件中配置端口(如9001)

// application.yml
server:
  port: 9001

3. provider類中確認要加入actuator依賴(此爲監控依賴)

// 所有Provider微服務提供類(8001/8002/8003)都需要提供監控依賴配置

// (8001/8002/8003)pom.xml

<!-- actuator 監控信息完善 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

4. 編寫主啓動類,上標@EnableHystrixDashboard標註

@SpringBootApplication
@EnableHystrixDashboard
public class DeptConsumer_DashBoard_App {

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

5. 啓動服務進行測試,訪問地址:http://localhost:9001/hystrix,(根據配置端口號),==看到刺蝟表示已經配置好了==


##### 如何監控

- 在dashboard界面中,填入需要監控的服務地址和端口號加上\hystrix.stream和監測間隔即可進入監控。(如http://localhost:8001/hystrix.stream

// 啓動相關工程:// microservicecloud-consumer-hystrix-dashboard   // 訪問: http://localhost:9001/hystrix
// 3個Eureka集羣:// microservicecloud-provider-dept-hystrix-8001
// 訪問: http://localhost:8001/dept/get/1,// 訪問: http://localhost:8001/hystrix.stream

##### 監控分析
- 七色:進入監控界面後會有其中顏色的數字,其含義可以對應右上角相同顏色的單詞表示的狀態,其值代表該狀態下觸發的次數
- 一圈:圈的大小代表該服務的流量,圈越大流量越大
- 一線:代表監控間隔中,服務被訪問的頻率的折線圖
- 通過觀察這些就可以在大量的實例中找出故障實例和高壓實例進行修復和維護

Dashboard監控說明圖:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章