Ribbon、Feign、Hystrix使用时的超时时间设置问题

本次主要记录公司项目微服务改造过程中所遇到的问题记录,以及解决方案(借鉴了一些博客资料),旨在记录、学习!!!

1.Ribbon、Feign、Hystrix使用时的超时时间设置问题

SpringCloud 2.2.5环境版本

1.Feign+Hystrix
  • Feign内部支持了断路器,所以不需要在启动类额外加上开启注解@EnableCircuitBreaker,只需要在配置文件中打开Feign自带的断路器
### 开启Feign自带的断路器
feign:
  hystrix:
    enabled: true
  • 用注解@FeignClient添加fallback类,该fallback类必须实现@FeignClient修饰的接口
@FeignClient(value = ApplicationNameConst.SERVER_DEMO_PROVIDER,fallback = HelloServiceFallback.class)
public interface HelloServiceClient 
{

    @GetMapping(value="/hello/{name}")
    String hello(@PathVariable("name") String name);

    @GetMapping(value="/hi/{name}")
    DataResponseBody hi(@PathVariable("name") String name);

    @GetMapping(value="/hi2/{name}")
    DataResponseBody hi2(@PathVariable("name") String name);
}
  • fallback熔断处理类
/**
 * @description Feign 熔断处理类
 * @date 2020-11-04
 */

@Component
public class HelloServiceFallback implements HelloServiceClient {

    @Override
    public String hello(String name) {
        return "Fail to ask ".concat(name).concat(" by feign!");
    }

    @Override
    public DataResponseBody hi(String name) {
        return DataResponseFactory.failed("hi name failed");
    }

    @Override
    public DataResponseBody hi2(String name) {
        return DataResponseFactory.failed("hi2 name failed");
    }
}
  • 熔断超时时间设置

Feign把复杂的http请求包装成我们只需要加注解就可以实现,但是底层使用的还是Ribbon。

Feign的调用,总共分两层,即Ribbon的调用和Hystrix(熔断处理)的调用,高版本的Hystrix默认是关闭的

**综上所得:**Feign的熔断超时时间需要同时设置Ribbon和Hystrix的超时时间设置

#Hystrix的默认超时设置
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 8000  #熔断器超时时间(毫秒)

# Ribbon的超时设置
ribbon:
  ReadTimeout: 8000  #响应超时(毫秒)
  ConnectTimeout: 5000 #连接超时(毫秒)
  • 不同实例分别配置

如果想更进一步,把超时时间细分到不同的service实例上也可以实现,如下:

@FeignClient(value ="hello-service",fallback = HelloServiceFallback.class)
public interface HelloServiceClient 
{

    @GetMapping(value="/hello/{name}")
    String hello(@PathVariable("name") String name);

    @GetMapping(value="/hi/{name}")
    DataResponseBody hi(@PathVariable("name") String name);

    @GetMapping(value="/hi2/{name}")
    DataResponseBody hi2(@PathVariable("name") String name);
}
#Hystrix的不同实例超时设置
hystrix:
  command:
    "HelloServiceClient#hello()":
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 8000  #熔断器超时时间(毫秒)

# Ribbon的超时设置
ribbon:
  ReadTimeout: 8000  #响应超时(毫秒)
  ConnectTimeout: 5000 #连接超时(毫秒)

关于Hystrix的配置,这里有官方文档说明

其中下面的配置文件中,替代***default***的是***HystrixCommandKey***,文档中有说明

2.Ribbon+Hystrix
  • 开启hystrix的断路器,一般可以加载启动类
@EnableCircuitBreaker //开启hystrix的断路器支持
@SpringBootApplication(scanBasePackages = "org.dubhe")
@EnableDiscoveryClient  //nacos客户端
public class DemoClientApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoClientApplication.classargs);
    }

    /**
     * 负载均衡
     * @return
     */

    @LoadBalanced
    @Bean
    public RestTemplate restTemplate() {
        return RestTemplateFactory.getRestTemplate();
    }
}
  • hystrix的默认基本配置

在使用ribbon时,只需要设置Hystrix的超时时间就可以了

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 9000  #毫秒
  • 不同实例分别配置1

@HystrixCommand注解中的commandkey定义成不同的值,然后的yaml配置文件中设置

@PreAuthorize("hasAuthority('user')")
@HystrixCommand(commandKey = "AskController-restAsk",fallbackMethod = "askFailed")
@GetMapping(value = "/rest")
public String restAsk(){
    return restTemplate.getForEntity("http://"+ ApplicationNameConst.SERVER_DEMO_PROVIDER +"/hello/"+name, String.class).getBody();
}
#Hystrix的不同实例超时设置
hystrix:
  command:
    "AskController-restAsk":
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 8000  #熔断器超时时间(毫秒)
  • 不同实例分别配置2
@PreAuthorize("hasAuthority('user')")
@HystrixCommand(fallbackMethod = "askFailed",commandProperties ={
    @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds" ,value="8000")
})
@GetMapping(value = "/rest")
public String restAsk(){
    return restTemplate.getForEntity("http://"+ ApplicationNameConst.SERVER_DEMO_PROVIDER +"/hello/"+name, String.class).getBody();
}

未完待续!!!

posted @ 2020-11-27 16:46  MrAshin  阅读(2193)  评论(0编辑  收藏  举报