Feign整合Hystrix实现熔断机制

首先加入对feign和hyStrix的依赖

 <dependency>
     <groupId>org.springframework.cloudgroupId>
     <artifactId>spring-cloud-starter-feignartifactId>
 dependency>
 <dependency>
    <groupId>org.springframework.cloudgroupId>
    <artifactId>spring-cloud-starter-netflix-hystrixartifactId>
dependency>

其次在启动类中加入对feign的支持

@EnableFeignClients

创建HelloService接口
在FeignClient注解中添加fallback,指定Hystrix熔断异常回调类HelloServiceHystrix,代码如下:

package com.tairan.chapter.feign.api;

import com.tairan.chapter.feign.api.hystrix.HelloServiceHystrix;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;

@FeignClient(value = "test",fallback = HelloServiceHystrix.class)
public interface HelloService {
     

    @RequestMapping("/hello")
    String getMessage() throws Exception;

}

创建HelloServiceHystrix类
创建HelloServiceHystrix类,并实现HelloService接口,代码如下:

package com.tairan.chapter.feign.api.hystrix;

import com.tairan.chapter.feign.api.HelloService;
import org.springframework.stereotype.Component;

/**
 * 当HelloService中的Feign调用失败或超时时,会调用该实现类的方法
 * 需要注意的是fallback指定的类一定要添加@Component将其加入到Spring容器
 */
@Component
public class HelloServiceHystrix implements HelloService {
     
    @Override
    public String getMessage() throws Exception {
     
        return "Get Message Failed!";
    }
}

注意:fallback指定的类一定要添加@Component将其加入到Spring容器

开启Feign对Hystrix的支持
在application.yml文件中添加如下配置:

feign:
  # Dalston SR1(待定)之后的版本默认关闭hystrix对feign的支持,如果想要使用fallback功能这里必须启用
  hystrix:
    enabled: true

运行测试:

  • 启动服务注册中心tairan-spring-cloud-eureka
  • 启动服务提供方tairan-spring-cloud-feign-provider
  • 启动服务消费方tairan-spring-cloud-feign-consumer
  • 访问tairan-spring-cloud-feign-consumer工程的/feign-hello接口,链接:http://localhost:8080/feign-hello,查看访问结果
  • 关闭服务提供方tairan-spring-cloud-feign-provider
  • 访问tairan-spring-cloud-feign-consumer工程的/feign-hello接口,链接:http://localhost:8080/feign-hello,查看访问结

执行4操作后,访问链接http://localhost:8080/feign-hello后,接口返回结果如下所示:
Feign整合Hystrix实现熔断机制_第1张图片
执行5操作后,访问链接http://localhost:8080/feign-hello后,接口返回结果如下所示:
Feign整合Hystrix实现熔断机制_第2张图片

feign的超时机制

目前基本使用Feign都是与ribbon结合使用的,最重要的两个超时是连接超时ConnectTimeout和读超时ReadTimeout
在Spring Cloud中使用Feign进行微服务调用分为两层:Ribbon的调用及Hystrix的调用。所以Feign的超时时间就是Ribbon和Hystrix超时时间的结合,而如果不启用Hystrix则Ribbon的超时时间就是Feign的超时时间配置,Feign自身的配置会被覆盖。
而如果开启了Hystrix,那么Ribbon的超时时间配置与Hystrix的超时时间配置则存在依赖关系,因为涉及到Ribbon的重试机制,所以一般情况下都是Ribbon的超时时间小于Hystrix的超时时间,否则会出现以下错误:

2019-07-12 11:10:20,238 397194 [http-nio-8084-exec-2] WARN  o.s.c.n.z.f.r.s.AbstractRibbonCommand - The Hystrix timeout of 40000ms for the command operation is set lower than the combination of the Ribbon read and connect timeout, 80000ms.

在Ribbon超时但Hystrix没有超时的情况下,Ribbon便会采取重试机制;而重试期间如果时间超过了Hystrix的超时配置则会立即被熔断(fallback)。
下面按优先级从高到低配置

默认配置
在默认配置下,Feign的超时时间配置如下:

    public class DefaultClientConfigImpl implements IClientConfig {
     
        public static final int DEFAULT_READ_TIMEOUT = 5000;
        public static final int DEFAULT_CONNECT_TIMEOUT = 2000;

从上面一看是2s和5s,但是这是个坑,因为在构造完这个类后,又使用ribbon的配置把默认配置覆盖掉了:

    @Bean
    @ConditionalOnMissingBean
    public IClientConfig ribbonClientConfig() {
     
        DefaultClientConfigImpl config = new DefaultClientConfigImpl();
        //此处还将DefaultClientConfigImpl内部的一个属性enableDynamicProperties改成了ture
        config.loadProperties(this.name);
        config.set(CommonClientConfigKey.ConnectTimeout, DEFAULT_CONNECT_TIMEOUT);
        config.set(CommonClientConfigKey.ReadTimeout, DEFAULT_READ_TIMEOUT);
        return config;
    }

ribbon全局配置:

ribbon:  
    ReadTimeout: 60000  
    ConnectTimeout: 60000

ribbon指定服务配置:
app-server为服务名

app-server:
  ribbon:
    ReadTimeout: 30000
    ConnectTimeout: 30000

Feign全局配置
需要注意的是connectTimeout和readTimeout必须同时配置,要不然不会生效,还是以ribbon为准

feign:
  client:
    config:
      default:
        connectTimeout: 10000
        readTimeout: 10000

Feign指定服务配置
和全局配置类似

feign:
  client:
    config:
      app-server:
        connectTimeout: 10000
        readTimeout: 10000

hystrix指定方法配置:

hystrix.command.xxx#yyy(zzz).execution.isolation.thread.timeoutInMilliseconds=mmm
xxx:要设置的某个FeignClient的类名
yyy:方法名
zzz:参数,如果是基础类型,就直接填基础类型:String/int;如果是某个对象,就直接填对象的类名
mmm:要设置的超时时间(毫秒)

示例:

hystrix.command.HelloService#getMessage().execution.isolation.thread.timeoutInMilliseconds=10000

上述设置可以使feign的方法超时时间设置为10秒钟

你可能感兴趣的:(Spring,Cloud,java)