ribbon组件的ConnectTimeOut和ReadTimeOut功能失效

  最近在学习springcloud微服务,在使用openfeign时,需要使用ribbon组件的ConnectTimeOut和ReadTimeOut功能
本次项目是由消费者和提供者组成,提供者故意延时3s模拟复杂业务,而消费者的对用户提供的服务采用了服务降级

提供者服务,由控制层调用

  1. package com.sgy.springcloud.service;
  2. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
  4. import com.sgy.springcloud.dao.PaymentDao;
  5. import com.sgy.springcloud.entities.Payment;
  6. import com.sgy.springcloud.services.BaseDaoServiceImpl;
  7. import org.springframework.stereotype.Service;
  8. import java.util.concurrent.TimeUnit;
  9. /**
  10. * Created by AaronShen on 2020/6/1
  11. */
  12. @Service
  13. public class PaymentServiceImpl extends BaseDaoServiceImpl<Payment,String, PaymentDao>
  14. implements PaymentService {
  15. /**
  16. * 模拟复杂业务
  17. * 3000表示当前线程超过3s后调用fallbackMethod中指定的方法
  18. * @param id
  19. */
  20. @HystrixCommand(fallbackMethod = "paymentInfoTimeOutHandle",commandProperties = {
  21. @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")
  22. })
  23. @Override
  24. public String paymentInfoTimeOut(Integer id) {
  25. // int i = 10 / 0 ;
  26. try {
  27. TimeUnit.SECONDS.sleep(3);
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31. String result = "当前线程:" + Thread.currentThread().getName() +
  32. "\t" + "paymentInfoTimeOut(id)" + "\t" + id +
  33. "\t" + "耗时(秒):5";
  34. return result;
  35. }
  36. private String paymentInfoTimeOutHandle(Integer id) {
  37. String result = "当前线程:" + Thread.currentThread().getName() +
  38. "\t" + "8090系统繁忙或者运行报错,请稍后再试试!!!" +
  39. "\t" + "服务降级";
  40. return result;
  41. }
  42. }

消费者

控制层

  1. package com.sgy.springcloud.controller;
  2. import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
  3. import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
  4. import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
  5. import com.sgy.springcloud.service.OrderService;
  6. import lombok.extern.slf4j.Slf4j;
  7. import org.springframework.web.bind.annotation.GetMapping;
  8. import org.springframework.web.bind.annotation.PathVariable;
  9. import org.springframework.web.bind.annotation.RestController;
  10. import javax.annotation.Resource;
  11. /**
  12. * Created by AaronShen on 2020/6/1
  13. */
  14. @RestController
  15. @Slf4j
  16. @DefaultProperties(defaultFallback = "paymentGlobalFallback")
  17. public class OrderController {
  18. @Resource
  19. OrderService orderService;
  20. @GetMapping("/hystrix/ok/{id}")
  21. public String orderInfoOk(@PathVariable(value="id") Integer id) {
  22. String result = orderService.paymentInfoOk(id);
  23. return result;
  24. }
  25. @GetMapping("/hystrix/timeout/{id}")
  26. // @HystrixCommand(fallbackMethod = "paymentInfoTimeOutHandle",commandProperties = {
  27. // @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
  28. // })
  29. @HystrixCommand
  30. public String orderInfoTimeOut(@PathVariable(value="id") Integer id) {
  31. String result = orderService.paymentInfoTimeOut(id);
  32. return result;
  33. }
  34. private String paymentInfoTimeOutHandle(Integer id) {
  35. String result = "当前线程:" + Thread.currentThread().getName() +
  36. "\t" + "我是消费者80,对方支付系统繁忙请10秒后再试试或者自己运行出错请检查自己!!!" +
  37. "\t" + "服务降级";
  38. return result;
  39. }
  40. // 下面是全局的fallback
  41. public String paymentGlobalFallback() {
  42. return "消费者Global Fallback异常";
  43. }
  44. }

服务接口

@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVER",fallback = OrderFallbackService.class)
public interface OrderService {

    @GetMapping("/hystrix/ok/{id}")
    String paymentInfoOk(@PathVariable(value="id") Integer id);

    @GetMapping("/hystrix/timeout/{id}")
    String paymentInfoTimeOut(@PathVariable(value="id") Integer id);
}
/**
 * Created by AaronShen on 2020/7/9
 */
@Service
public class OrderFallbackService implements OrderService{

    @Override
    public String paymentInfoOk(Integer id) {
        return "fallback--paymentInfoOk,支付服务宕机了";
    }

    @Override
    public String paymentInfoTimeOut(Integer id) {
        return "fallback--paymentInfoTimeOut,支付服务宕机了";
    }
}

出现的问题

我在消费者的控制层中的orderInfoTimeOut方法中直接标注@HystrixCommand,则调用全局的服务降级,但是呢?服务提供者故意延时3s,模拟复杂业务,结果消费者,每回访问都在调用服务降级。

原因分析

Hystrix默认超时时间是1秒,我们可以通过hystrix源码看到,

找到 hystrix-core.jar com.netflix.hystrix包下的HystrixCommandProperties类

default_executionTimeoutInMilliseconds属性局势默认的超时时间

ribbon组件的ConnectTimeOut和ReadTimeOut功能失效 - 图1

解决问题

引入的依赖,千万别引入错了

<!--引入Hystrix依赖:-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

application.yml配置文件加上

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000

接着探索

当我们经过以上的步骤之后,服务降级的超时时间是生效了,但是我使用了feign,feign底层使用的是ribbon,对远程服务进行调用

依旧出现服务降级问题分析

这回出现服务降级的原因就是,ribbon访问超时了,但是我明明配置了超时时间啊

# 设置feign客户端超时时间(OpenFeign默认支持Ribbon)
ribbon:
  ReadTimeOut: 10000           # 建立连接所用时间,适用于网络状况正常的情况下,两端连接所用的时间
  ConnectTimeOut: 10000        # 建立连接后,从服务器读取到的可用资源所用的时间

问题解决

使用中发现ribbon组件的ConnectTimeOut和ReadTimeOut功能并没有生效,报错代码示下:

查找maven导的依赖发现ribbon包冲突了,所以我选用feign里面的ribbon:

feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        # 设置feign客户端超时时间(OpenFeign默认支持Ribbon)
        #简历连接所用的时间,适用于网络状况正常的情况下,两端连接所需要的时间
        ConnectTimeout: 5000
        #指建立连接后从服务端读取到可用资源所用的时间
        ReadTimeout: 10000