Ribbon超时

全局设置

1
2
3
4
5
6
7
8
9
ribbon:
  ReadTimeout: 10000
  ConnectTimeout: 10000
  #对当前服务的重试次数
  MaxAutoRetries: 0
  #切换相同Server的次数
  MaxAutoRetriesNextServer: 1
  eureka:
    enabled: true

源码org.springframework.cloud.netflix.zuul.filters.route.support.AbstractRibbonCommand.java

  • RibbonTimeout

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    
    protected static int getRibbonTimeout(
      IClientConfig config, String commandKey) {
    	int ribbonTimeout;
      if (config == null) {
    		ribbonTimeout = RibbonClientConfiguration.DEFAULT_READ_TIMEOUT + RibbonClientConfiguration.DEFAULT_CONNECT_TIMEOUT;
      } else {
        	int ribbonReadTimeout = getTimeout(config, commandKey, "ReadTimeout",
    	IClientConfigKey.Keys.ReadTimeout, RibbonClientConfiguration.DEFAULT_READ_TIMEOUT);
          int ribbonConnectTimeout = getTimeout(config, commandKey, "ConnectTimeout",
                                                IClientConfigKey.Keys.ConnectTimeout, RibbonClientConfiguration.DEFAULT_CONNECT_TIMEOUT);
          int maxAutoRetries = getTimeout(config, commandKey, "MaxAutoRetries",
                                          IClientConfigKey.Keys.MaxAutoRetries, DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES);
          int maxAutoRetriesNextServer = getTimeout(config, commandKey, "MaxAutoRetriesNextServer",
                                                    IClientConfigKey.Keys.MaxAutoRetriesNextServer, DefaultClientConfigImpl.DEFAULT_MAX_AUTO_RETRIES_NEXT_SERVER);
          ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1);
      }
      return ribbonTimeout;
    }
  • HystrixTimeout

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    protected static int getHystrixTimeout(IClientConfig config, String commandKey) {
      int ribbonTimeout = getRibbonTimeout(config, commandKey);
      DynamicPropertyFactory dynamicPropertyFactory = DynamicPropertyFactory.getInstance();
      // 获取默认的hytrix超时时间
      int defaultHystrixTimeout = dynamicPropertyFactory.getIntProperty("hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds",
                                                                        0).get();
      获取具体服务的hytrix超时时间
          int commandHystrixTimeout = dynamicPropertyFactory.getIntProperty("hystrix.command." + commandKey + ".execution.isolation.thread.timeoutInMilliseconds",
                                                                            0).get();
      int hystrixTimeout;
      if(commandHystrixTimeout > 0) {
          hystrixTimeout = commandHystrixTimeout;
      }
      else if(defaultHystrixTimeout > 0) {
          hystrixTimeout = defaultHystrixTimeout;
      } else {
          hystrixTimeout = ribbonTimeout;
      }
      // hytrix超时时间 < ribbon超时时间就会警告
      if(hystrixTimeout < ribbonTimeout) {
          LOGGER.warn("The Hystrix timeout of " + hystrixTimeout + "ms for the command " + commandKey +
                      " is set lower than the combination of the Ribbon read and connect timeout, " + ribbonTimeout + "ms.");
      }
      return hystrixTimeout;
    }

局部设置

1
2
3
4
5
#与spring.application.name 一致
service-id:
  ribbon:
    ReadTimeout: 1000
    ConnectTimeout: 1000

Zuul超时

官方文档: http://cloud.spring.io/spring-cloud-static/Edgware.RELEASE/single/spring-cloud.html#_zuul_timeouts

Zuul的路由使用Ribbon

If Zuul is using service discovery than you need to configure these timeouts via Ribbon properties, ribbon.ReadTimeout and ribbon.SocketTimeout.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
ribbon:
  ReadTimeout: 10000
  ConnectTimeout: 10000
  #对当前服务的重试次数
  MaxAutoRetries: 0
  #切换相同Server的次数
  MaxAutoRetriesNextServer: 1
  eureka:
    enabled: true

hystrix:
  threadpool:
    default:
      coreSize: 10 ##并发执行的最大线程数,默认10
      maxQueueSize: 10 ##BlockingQueue的最大队列数
      queueSizeRejectionThreshold: 5 ##即使maxQueueSize没有达到,达到queueSizeRejectionThreshold该值后,请求也会被拒绝
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 50000

Zuul的路由不使用Ribbon(URL形式)

例如这样的路由配置

1
2
3
4
5
zuul:
  routes:
  	user-route:   #该配置方式中,user-route只是给路由一个名称,可以任意起名。
      url: http://localhost:8000/ # 指定的url
      path: /user/**              # url对应的路径。

If you have configured Zuul routes by specifying URLs than you will need to use zuul.host.connect-timeout-millis and zuul.host.socket-timeout-millis.

1
2
3
4
zuul:
  host:
    connect-timeout-millis: 5000 #默认2000
    socket-timeout-millis: 30000  #默认10000

Hystrix超时

Hystrix的默认超时时间是1秒。默认开启超时机制。如需关闭Hystrix的超时,可将timeout.enabled设置为false。Hystrix的超时 > 其他组件的超时,否则将导致重试特性失效。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
hystrix:
  command:
    default:
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 50000
#设置不同微服务的超时时间,CommandKey就是service id:hystrix.command
#hystrix.command.[CommandKey].execution.isolation.thread.timeoutInMilliseconds

Feign的http请求组件

源代码:org.springframework.cloud.netflix.feign.ribbon.FeignRibbonClientAutoConfiguration.java

1
2
3
4
5
6
7
8
9
feign:
  hystrix:
    # 在feign中开启hystrix功能,默认情况下feign不开启hystrix功能
    enabled: true
  # 配置httpclient线程池
  httpclient:
    enabled: true
  okhttp:
    enabled: false
  • 默认连接为:HttpURLConnection。

源码查看这里:new Default((SSLSocketFactory)null

1
2
3
4
5
6
   //默认配置
  @Bean
  @ConditionalOnMissingBean
  public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
      return new LoadBalancerFeignClient(new Default((SSLSocketFactory)null, (HostnameVerifier)null), cachingFactory, clientFactory);
  }
  • 可选配置:

    • OkHttpFeignLoadBalancedConfiguration

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      
      @Configuration
      @ConditionalOnClass({OkHttpClient.class})
      @ConditionalOnProperty(
      value = {"feign.okhttp.enabled"},
      matchIfMissing = true
      )
      protected static class OkHttpFeignLoadBalancedConfiguration {
      @Autowired(
          required = false
      )
      private okhttp3.OkHttpClient okHttpClient;
          
      protected OkHttpFeignLoadBalancedConfiguration() {
      }
          
      @Bean
      @ConditionalOnMissingBean({Client.class})
      public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
          OkHttpClient delegate;
          if (this.okHttpClient != null) {
              delegate = new OkHttpClient(this.okHttpClient);
          } else {
              delegate = new OkHttpClient();
          }
          
          return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
      }
      }
    • HttpClientFeignLoadBalancedConfiguration

       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      
      @Configuration
      @ConditionalOnClass({ApacheHttpClient.class})
      @ConditionalOnProperty(
      value = {"feign.httpclient.enabled"},
      matchIfMissing = true
      )
      protected static class HttpClientFeignLoadBalancedConfiguration {
      @Autowired(
          required = false
      )
      private HttpClient httpClient;
          
      protected HttpClientFeignLoadBalancedConfiguration() {
      }
          
      @Bean
      @ConditionalOnMissingBean({Client.class})
      public Client feignClient(CachingSpringLoadBalancerFactory cachingFactory, SpringClientFactory clientFactory) {
          ApacheHttpClient delegate;
          if (this.httpClient != null) {
              delegate = new ApacheHttpClient(this.httpClient);
          } else {
              delegate = new ApacheHttpClient();
          }
          
          return new LoadBalancerFeignClient(delegate, cachingFactory, clientFactory);
      }
      }

max-semaphores

可以通过Hystrix的命名规则来设置,但被zuul重新设计了,使得在zuul中semaphores的最大并发请求有4个方法的参数可以设置,如果4个参数都存在优先级(1~4)由高到低

1.zuul.eureka.api.semaphore.maxSemaphores

2.zuul.semaphore.max-semaphores

3.hystrix.command.api.execution.isolation.semaphore.maxConcurrentRequests

4.hystrix.command.default.execution.isolation.semaphore.maxConcurrentRequests