FeignClient超時配置

1前沿

使用Feign調用接口分兩層,ribbon的調用和hystrix的調用,因此ribbon的超時時間和Hystrix的超時時間的結合就是Feign的超時時間java

1.1ribbon配置

ribbon:
  OkToRetryOnAllOperations: false #對全部操做請求都進行重試,默認false
  ReadTimeout: 3000   #負載均衡超時時間,默認值5000
  ConnectTimeout: 2000 #ribbon請求鏈接的超時時間,默認值2000
  MaxAutoRetries: 0     #對當前實例的重試次數,默認0
  MaxAutoRetriesNextServer: 0 #對切換實例的重試次數,默認1

1.2 hystrix熔斷配置

hystrix:
  command:
    default:  #default全局有效,service id指定應用有效
      execution:
        timeout:
          #是否開啓超時熔斷
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 4000 #斷路器超時時間,默認1000ms

feign:
  hystrix:
    enabled: true

2測試各個配置的效果

     開了一個Eureka服務中心web

     開了兩個個服務eureka-client,端口分別爲87628763,進行負載均衡spring

eureka-client的方法:服務器

package com.example.cloud_client;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

/**
 * @author 莊勇
 * @date 2018/12/11 16:27
 */
@RestController
public class TestController {
    @Value("${server.port}")
    String port;

    @Value("${spring.application.name}")
    String serviceName;

    @RequestMapping(value="/test", method = RequestMethod.GET)
    public String index(@RequestParam("millis") int millis) throws InterruptedException {
        System.out.println("8762---"+System.currentTimeMillis());
        Thread.sleep(millis);

        return "serviceName=" + serviceName + "-------port=" + port;
    }

}

feignClient網絡

eureka-feign調用client的方法,經過傳參數millis來控制client線程休眠的時間app

controller負載均衡

package com.example.eurekafeignclient;

import com.example.eurekafeignclient.inter.FeignInterface;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author 莊勇
 * @date 2018/12/12 9:37
 */
@RestController
public class FeiConsumerController {
@Autowired
FeignInterface feignInterface;

    @RequestMapping("eureka-client")
    public String feignConsumer(@RequestParam int millis) {

        long start = System.currentTimeMillis();
        System.out.println(start);
        String a = feignInterface.IndexInfo(millis);
        long end = System.currentTimeMillis();
        System.out.println(end);
        System.out.println("調用eureka-client服務時長" + (end-start) + "ms");
        return a;
    }
}

serveiceide

package com.example.eurekafeignclient.inter;

import com.example.eurekafeignclient.HelloServiceFallback;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * @author 莊勇
 * @date 2018/12/12 9:35
 */
@FeignClient(value="eureka-client",fallback = HelloServiceFallback.class)
public interface  FeignInterface {
    @RequestMapping(value="/test", method = RequestMethod.GET)
    String IndexInfo(@RequestParam(value="millis") int millis);
}

熔斷方法fallback測試

package com.example.eurekafeignclient;

import com.example.eurekafeignclient.inter.FeignInterface;
import org.springframework.stereotype.Component;

/**
 * @author 莊勇
 * @date 2018/12/12 10:27
 */
@Component
public class HelloServiceFallback  implements FeignInterface {

    @Override
    public String IndexInfo(int millis) {
        System.out.println("熔斷");
        return "熔斷";
    }
}

主要測試幾種狀況spa

1, ribbon的超時時間和Hystrix的超時時間的關係

2,ribbon的超時時間和Hystrix的超時時間的何時生效

3,重試時候參數配置

4,其餘

測試1(無重試)

無重試1

(ReadTimeout和timeoutInMilliseconds關係)

    全局參數:ribbon和hystrix參數設置沒有重試

OkToRetryOnAllOperations: false
    MaxAutoRetries: 0     #對當前實例的重試次數,默認0
    MaxAutoRetriesNextServer: 0 #對切換實例的重試次數,默認1
    ReadTimeout: 3000   #負載均衡超時時間,默認值5000
    ConnectTimeout: 1000 #ribbon請求鏈接的超時時間,默認值2000
    timeoutInMilliseconds: 5000 #斷路器超時時間,默認1000ms

條件1:Port=8762  Millis=1000ms   Port=8763  Millis=1000ms  

結果:   打印port=8762----------調用eureka-client服務時長1013ms

 打印port=8763----------調用eureka-client服務時長1011ms

條件2:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms  

 打印port=8762----------熔斷1544750879175調用eureka-client服務時長3003ms

 打印port=8763----------熔斷 1544750757822 調用eureka-client服務時長3003ms

條件3:Port=8762  Millis=5500ms   Port=8763  Millis=5500ms  

 打印port=8762----------熔斷1544750879175調用eureka-client服務時長3005ms

 打印port=8763----------熔斷1544750879175調用eureka-client服務時長3007ms

無重試2

如下修改了參數ReadTimeout和timeoutInMilliseconds進行測試

OkToRetryOnAllOperations: false
    MaxAutoRetries: 0     #對當前實例的重試次數,默認0
    MaxAutoRetriesNextServer: 0 #對切換實例的重試次數,默認1
    ReadTimeout: 5000   #負載均衡超時時間,默認值5000
    ConnectTimeout: 1000 #ribbon請求鏈接的超時時間,默認值2000
    timeoutInMilliseconds: 3000 #斷路器超時時間,默認1000ms

條件4:Port=8762  Millis=5500ms   Port=8763  Millis=5500ms  

 打印port=8762----------熔斷1544750879175調用eureka-client服務時長3364ms

 打印port=8763----------熔斷1544750879175調用eureka-client服務時長3005ms

條件5:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms  

 打印port=8762----------熔斷1544750879175調用eureka-client服務時長3004ms

 打印port=8763----------熔斷1544750879175調用eureka-client服務時長3003ms

條件6:Port=8762  Millis=1000ms   Port=8763  Millis=1000ms  

 打印port=8762----------調用eureka-client服務時長1010ms

 打印port=8763----------調用eureka-client服務時長1003ms

停掉8762和8763服務

條件7:Port=8762  Millis=1000ms   Port=8763  Millis=1000ms

打印----------熔斷1544754831161調用eureka-client服務時長1007ms

條件8:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms

打印----------熔斷1544754945541調用eureka-client服務時長1007ms

條件9:Port=8762  Millis=5500ms   Port=8763  Millis=5500ms

打印----------熔斷1544755009533調用eureka-client服務時長1006ms

結論:

無重試的時候,超時時間與ReadTimeout和timeoutInMilliseconds最小值相關,此時誰的值小誰生效

停掉服務時,客戶服務中止時,超時時間採用的是timeoutInMilliseconds的默認時間1000ms???

 

測試2(有重試)

OkToRetryOnAllOperations: false
    MaxAutoRetries: 1     #對當前實例的重試次數,默認0
    MaxAutoRetriesNextServer: 0 #對切換實例的重試次數,默認1
    ReadTimeout: 3000   #負載均衡超時時間,默認值5000
    ConnectTimeout: 1000 #ribbon請求鏈接的超時時間,默認值2000
    timeoutInMilliseconds: 5000 #斷路器超時時間,默認1000ms

重試次數=(MaxAutoRetries+MaxAutoRetriesNextServer+MaxAutoRetriesNextServer*MaxAutoRetries)  測試中可驗證

條件10:Port=8762  Millis=1000ms   Port=8763  Millis=1000ms  

打印----------1544756976651調用eureka-client服務時長1955ms

條件11:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms  

打印8762----------熔斷1544757079644調用eureka-client服務時長5017ms

打印8763----------熔斷1544757189984調用eureka-client服務時長5004ms

此時出現了重試 修改參數

OkToRetryOnAllOperations: false
    MaxAutoRetries: 1     #對當前實例的重試次數,默認0
    MaxAutoRetriesNextServer: 0 #對切換實例的重試次數,默認1
    ReadTimeout: 3000   #負載均衡超時時間,默認值5000
    ConnectTimeout: 1000 #ribbon請求鏈接的超時時間,默認值2000
    timeoutInMilliseconds: 10000 #斷路器超時時間,默認1000ms

條件12:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms  

打印8762----------熔斷1544757421610調用eureka-client服務時長6009ms

打印8762----------熔斷1544757542162調用eureka-client服務時長6009ms
打印8762----------熔斷1544757546794調用eureka-client服務時長6010ms

此時修改參數MaxAutoRetriesNextServer: 1 #對切換實例的重試次數,默認1

OkToRetryOnAllOperations: false
    MaxAutoRetries: 1     #對當前實例的重試次數,默認0
    MaxAutoRetriesNextServer: 1 #對切換實例的重試次數,默認1
    ReadTimeout: 3000   #負載均衡超時時間,默認值5000
    ConnectTimeout: 1000 #ribbon請求鏈接的超時時間,默認值2000
    timeoutInMilliseconds: 10000 #斷路器超時時間,默認1000ms

條件13:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms  

結果:打印

熔斷1544757776401調用eureka-client服務時長12098ms
熔斷1544757776401調用eureka-client服務時長12552ms
熔斷1544757776401調用eureka-client服務時長12707ms
熔斷1544757776401調用eureka-client服務時長12403ms
熔斷1544757776401調用eureka-client服務時長12763ms
熔斷1544757776466調用eureka-client服務時長12008ms

OkToRetryOnAllOperations: false
    MaxAutoRetries: 1     #對當前實例的重試次數,默認0
    MaxAutoRetriesNextServer: 1 #對切換實例的重試次數,默認1
    ReadTimeout: 3000   #負載均衡超時時間,默認值5000
    ConnectTimeout: 1000 #ribbon請求鏈接的超時時間,默認值2000
    timeoutInMilliseconds: 5000 #斷路器超時時間,默認1000ms

條件13:Port=8762  Millis=3500ms   Port=8763  Millis=3500ms  

 

結果:打印

熔斷1544759011132調用eureka-client服務時長5003ms

於此同時 8762服務器打印了

8763服務器打印了

說明重試並無結束

結論:

重試次數=(MaxAutoRetries+MaxAutoRetriesNextServer+MaxAutoRetriesNextServer*MaxAutoRetries)

重試時間=(MaxAutoRetries+MaxAutoRetriesNextServer+MaxAutoRetriesNextServer*MaxAutoRetries)*ReadTimeout+網絡響應時間

而且因爲重試應爲執行熔斷後而中止重試,從而形成沒必要要的狀況發生,所以熔斷時間應該在重試時間以後,

(MaxAutoRetries+MaxAutoRetriesNextServer+MaxAutoRetriesNextServer*MaxAutoRetries)*ReadTimeout+網絡響應時間+ReadTimeout<timeoutInMilliseconds