1. 程式人生 > >SpringCloud——斷路器(Hystrix)

SpringCloud——斷路器(Hystrix)

一、斷路器(Hystrix)介紹

         在一個分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,如何能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,這個就是Hystrix需要做的事情。Hystrix提供了熔斷、隔離、Fallback、cache、監控等功能,能夠在一個、或多個依賴同時出現問題時保證系統依然可用。

         Netflix創造了一個呼叫的庫Hystrix實現了斷路器圖案。在微服務架構中,通常有多層服務呼叫。

         較低級別的服務中的服務故障可能導致使用者級聯故障。當對特定服務的呼叫達到一定閾值時(Hystrix中的預設值為5秒內的20次故障),電路開啟,不進行通話。在錯誤和開路的情況下,開發人員可以提供後備。

         開放式電路會停止級聯故障,並允許不必要的或失敗的服務時間來癒合。回退可以是另一個Hystrix保護的呼叫,靜態資料或一個正常的空值。回退可能被連結,所以第一個回退使得一些其他業務電話又回到靜態資料。

二、實現程式碼測試

  建立工程結構,如圖:

三、Ribbon使用斷路器

  1、在原來service-hystrix-ribbon工程程式碼的基礎上,新增spring-cloud-starter-netflix-hystrix的起步依賴:

<dependency>
       <groupId>org.springframework.cloud</groupId>
       <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

  2、啟動類ServiceHystrixRibbonApplication.java添加註解@EnableHystrix來開啟Hystrix,程式碼如下:

package com.example.demo.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableHystrix
public class ServiceHystrixRibbonApplication {

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

	@Bean
	@LoadBalanced
	RestTemplate restTemplate(){
		return new RestTemplate();
	}
}

3、修改Service介面,在test方法上加上@HystrixCommand註解,在方法上建立熔斷器的功能,指定fallbackMethod熔斷方法,熔斷方法直接返回了一個字串。程式碼如下:

package com.example.demo.hystrix.servcie.impl;

import com.example.demo.hystrix.servcie.TestRibbonService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * 路徑:com.example.demo.hystrix.servcie.impl
 * 類名:
 * 功能:《用一句描述一下》
 * 備註:
 * 建立人:typ
 * 建立時間:2018/9/12 16:16
 * 修改人:
 * 修改備註:
 * 修改時間:
 */
@Service
public class TestRibbonServiceImpl implements TestRibbonService {

    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "error")
    public String test(String name) {
        return restTemplate.getForObject("http://HYSTRIX-CLIENT/holle?name="+name,String.class);
    }

    public String error(String name){
        return name+" error!";
    }
}
張三---------------8082
張三 error!

四、Feign使用斷路器

        Hystrix支援回退的概念:當電路斷開或出現錯誤時執行的預設程式碼路徑。要為給定的@FeignClient啟用回退,請將fallback屬性設定為實現回退的類名。

1、Feign是自帶斷路器的,但它沒有預設開啟。修改application.yml檔案,新增開啟斷路器

feign:
  hystrix:
    enabled: true

2、修改Service介面,只需要在FeignClient的TestFeignService介面的註解中加上fallback的指定類就就可以,程式碼入下:

package com.example.demo.hystrix.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 路徑:com.example.demo.hystrix.service
 * 類名:
 * 功能:《用一句描述一下》
 * 備註:
 * 建立人:typ
 * 建立時間:2018/9/12 16:08
 * 修改人:
 * 修改備註:
 * 修改時間:
 */
@FeignClient(value = "hystrix-client", fallback = TestFeignServiceFallback.class )
public interface TestFeignService {

    @RequestMapping(value = "/holle",method = RequestMethod.GET)
    public String getByClientOne(@RequestParam(value = "name")String name);
}

3、建立TestFeignServiceFallback.java類,需要實現TestFeignService介面,並將該類注入到spring的Ioc容器中,程式碼如下:

package com.example.demo.hystrix.service;

import org.springframework.stereotype.Component;

/**
 * 路徑:com.example.demo.hystrix.service.impl
 * 類名:
 * 功能:《用一句描述一下》
 * 備註:
 * 建立人:typ
 * 建立時間:2018/9/12 16:41
 * 修改人:
 * 修改備註:
 * 修改時間:
 */
@Component
public class TestFeignServiceFallback implements TestFeignService {

    @Override
    public String getByClientOne(String name) {
        return name+" error!";
    }
}
張三--------------8082
張三  error!