这大概是全网最详细的教你如何在 Spring Cloud 中使用 Hystrix 的文章了

320 阅读4分钟

一、简单使用

fsh-substitution服务中增加Hystrix的依赖,如以下代码所示:

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

在启动类上添加@EnableHystrix或者@EnableCircuitBreaker。注意,@EnableHystrix 中包含了@EnableCircuitBreaker

然后改造之前的callHello方法,在上面增加一个@HystrixCommand注解,用于指定依赖服务调用延迟或失败时调用的方法,如以下代码所示:

@GetMapping ("/ca11Hel1o")
@HystrixCommand(fallbackMethod = "defaultCal1Hello")
public String callHe11o() {
    String result = restTemplate.getForobject("http://fsh-house/house/hel1o",String.class);
    return result;
}

当调用失败触发熔断时会用defaultallHello方法来回退具体的内容,定义default-CallHello方法的代码,如以下代码所示:

pub1ic String defaultCal1Hello() {
    return "fail";
}

只启动fsh-substitution服务而不启动fsh-house服务,调用/alHello接口,可以看到返回的内容是"fail"。

将启动类上的@EnableHystrix去掉,重启服务,再次调用/callHello接口可以看到返回的是500错误信息,这个时候就没有用到回退功能了。

{
    code: 500,
    message: "I/O error on GET request for "http: //fsh-house/ house/hello":
        fsh-house; nested exception is java . net . UnknownHostException:
        fsh-house" ,
    data: null
}

二、配置详解

HystrixCommand中除了fallbackMethod 还有很多的配置,下面我们来看看这些配置:

image.png

image.png

image.png

image.png

官方的配置信息文档请参考: github.com/Netflix/Hys… 。上面列出来的都是Hystrix的配置信息,在Spring Cloud中如何使用呢?只需要在接口的方法上面使用HystrixCommand注解( 见下面代码),指定对应的属性即可。

@HystrixCommand(fallbackMethod = "defaultcallHello",commandProperties = {
    @HystrixProperty (
        name= " execution. isolation. strategy",
        value = "THREAD" )
    }
)
@GetMapping("/cal1He1lo")
public String cal1He11o() {
    String result =restTemplate .getForobject (
        "http://fsh-house/house/he11o", String. class);
    return result;
}

三、Feign整合Hystrix服务容错

首先需要执行第一节中的集成步骤,然后在属性文件中开启Feign 对Hystrix的支持:

feign.hystrix.enabled=true 

1. Fallback 方式

在Feign的客户端类上的@FeignClient注解中指定fallback进行回退(见下面代码),改造fsh-house的客户端类HouseRemoteClient, 为其配置fallback。

@FeignClient(value  = "fsh-house", . path = "/house",configuration =
FeignConfiguration.class, fallback = HouseRemoteClientHystrix.class)
public interface HouseRemoteClient{

    @GetMapping("/ {houseId}")
    HouseInfoDto hosueInfo (@PathVariable( "houseId" )Long houseId);

}

HouseRemoteClientHystrix类需要实现HouseRemoteClient类中所有的方法,返回回退时的内容,如以下代码所示:

@Component
pub1ic class HouseRemoteClientHystrix implements HouseRemoteClient {
    @Override
    public HouseInfoDto hosueInfo(Long houseId) {
        return new HouseInfoDto( ) ;
    }
}

启动fsh-substitution服务,停掉所有fsh-house服务,然后访问 htp://ocalhost:8082/substitution/1 接口,这个时候fsh-house服务是不可用的,必然会触发回退,返回的内容是正常的格式,只是house对象是空的,这证明回退生效了。在这种情况下,如果你的接口调用了多个服务的接口,那么只有fsh-house服务会没数据,不会影响别的服务,如果不用Hystrix回退处理,整个请求都将失败。

{
    code:200,
    message:"",
    data: {
        id:1,
        money:100.12,
        house: {
            id :null,
            city :nu1l,
            region:null,
            name : null
        }
    }
}

下面我们将启用 Hystrix 断路器禁用:

feign.hystrix.enabled=false 

再次访问 http://localhost:8082/substitution/1 可以看到返回的就是500错误了,整个请求失败。

{
    code:500,
    message: "Failed to connect to localhost/0:0:0:0:0:0:0:1:8083 executing GET
    http://fsh-house/house/1",
    data:null
}

2. FallbackFactory 方式

通过fallback已经可以实现服务不可用时回退的功能,如果你想知道触发回退的原因,可以使用FallbackFactory来实现回退功能,如以下代码所示:

@Component
public class HouseRemoteClientFallbackFactory implements FallbackFactory<HouseRemoteClient> {
    @Override
    public HouseRemoteClient create( final Throwable cause) {
        return new HouseRemoteClient() {
            @Override
            public HouseInfoDto hosueInfo(Long houseId) {
                HouseInfoDto info = new HouseInfoDto( );
                info. setData (new HouseInfo(1L, "", "", cause . getMessage()));
                return info;
            }
        };
    }
}

FallbackFactory的使用就是在@FeignClient中用fallbackFactory 指定回退处理类,如以下代码所示:

@FeignClient (value = "fsh-house",path = "/house”
configuration = FeignConfiguration.class,
fallbackFactory = HouseRemoteClientFallbackFactory.class)

在这个回退处理的时候,将异常信息设置到HouseInfo中的name属性中了,我们重启fsh-substitution,调用接口,可以看到异常信息返回在结果里面了,FallbackFactoryFallback 唯一的区别就在这里。

四、Feign 中禁用 Hystrix

禁用Hystrix还是比较简单的,目前有两种方式可以禁用,其中一种是在属性文件中进行全部禁用。

feign.hystrix.enabled=false 

另一种是通过代码的方式禁用某个客户端,在Feign的配置类中增加代码,如以下代码所示:

@Configuration
public class FeignConfiguration {
    @Bean
    @Scope("prototype" )
    public Feign. Builder feignBuilder() {
        return Feign.builder();
    }
}