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();
}

未完待續!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM