hystrix ,feign,ribbon的超時時間配置,以及原理分析


 背景,網上看到很多關於hystrix的配置都是沒生效的,如:

 

 

 

 

 一.先看測試環境搭建:

 

 order 服務通過feign 的方式調用了product 服務的getProductInfo 接口

//------------ order 服務的調用接口---------------

@FeignClient(name ="product",fallback =ProductHystrix.class)
@Primary
public interface ProductService {
    @RequestMapping("/info/{id}")
    Product getProductInfo(@PathVariable("id") Integer id);
}


@Component
public class ProductHystrix implements ProductService{
    @Override
    public Product getProductInfo(Integer id) {
        System.out.println("被熔斷;了");
        Product product = new Product();
        product.setName("熔斷了。。。。。");

        return product;
    }
}

// product 服務提供的接口------------------
@Controller
public class ProductController {
    @RequestMapping("/info/{id}")
    @ResponseBody
    @MyLogAnnotation
    public Product getProductInfo(@PathVariable("id") Integer id){
        Product product = new Product();
        product.setId(id);
        product.setName("蘋果手機");

        return product;
    }
}

order 服務的application.yml 開啟feign:hystrix:enabled: true
二. Hystrix 的超時時間怎么設置:

直接上代碼:hystrix 任何相關配置都可以在下面的配置類配置,我這里修改了核心線程數和最大隊列數已經超時時間

package com.yang.xiao.hui.order.controller;

import com.netflix.hystrix.*;
import feign.Feign;
import feign.Target;
import feign.hystrix.HystrixFeign;
import feign.hystrix.SetterFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import java.lang.reflect.Method;


@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
public class FeignConfig {

    @Bean
    @Scope("prototype")
    @ConditionalOnProperty(name = "feign.hystrix.enabled")
    public Feign.Builder feignHystrixBuilder() {
        HystrixFeign.Builder builder = HystrixFeign.builder();
        SetterFactory setterFactory= new SetterFactory(){

            @Override
            public HystrixCommand.Setter create(Target<?> target, Method method) {
                String groupKey = target.name();
                String commandKey = Feign.configKey(target.type(), method);
                //HystrixThreadPoolProperties 線程池相關配置
                HystrixThreadPoolProperties.Setter setter = HystrixThreadPoolProperties.Setter().withCoreSize(100).withMaxQueueSize(200);
                //HystrixCommandProperties 熔斷器相關屬性配置
                HystrixCommandProperties.Setter setter1 = HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(6000);

                return HystrixCommand.Setter
                        .withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                        .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
                        .andThreadPoolPropertiesDefaults(setter)
                        .andCommandPropertiesDefaults(setter1);


            }
        };
        builder.setterFactory(setterFactory);

        return builder;
    }
}

啟動服務:通過瀏覽器輸入http://localhost:8674/info/3 調用order 服務

 

 

 

 

 跟進去看HystrixCommand的創建:

 

 

 

 由此可見線程池和熔斷超時時間都已經改變了,證明我們的配置生效了

原理分析:

在FeignClientsConfiguration這個配置類中有一段代碼:

 

 然后跟進看到默認的對象:

 

 

 HystrixCommandProperties對象有個默認的超時時間,默認是1s:

 

 

 那么,我們根據上面的分析,當容器中存在HystrixFeign.builder就不會再創建該bean 了,所以我們可以自己創建一個HystrixFeign.builder 然后調用setterFactory(SetterFactory setterFactory)來修改默認的配置,也就是上面我們自己定義的配置類

熔斷器的熔斷時間是從調用下面的方法開始計算的:

 

三.feign超時時間怎么設置?

我們繼續跟進剛才的調用方法:

 

 

 

 

 在這里默認連接時間是10s,讀取時間是60s,那么這個類是怎么創建的呢?

 

 

 

 

 

 從上面可以知道,Options對象默認已經有個時間配置了,然而我們繼續跟蹤代碼:

 

 

 

 

 

 我們看這里:

 

 

 

 

 

 Options對象經過getClientConfig(options, clientName) 方法,就從10s的連接時間變成了1s,60s的讀取時間也變成了1s,上面源碼分析可以知道:

如果我們配置了feign的超時時間,那么就會以我們配置的時間為准,如果沒有配置,那么就取ribbon的超時時間,2者只能有一個生效,而ribbon默認超時時間是1秒

 

 

 

繼續跟進:

 

 

 

 

 

 

 

 

 上述代碼可見,feign或者ribbon所配置的超時時間,最終都是在HttpUrlConnection中生效

那么,我們如何修改feign的配置時間呢?

 

我們回到這里:

 

 這里說了,如果容器沒有該bean才會默認創建,那我們就自己創建一個注入到spring容器中:

在order 服務中:

@Configuration

public class Config {
    @Bean
    public Request.Options feignRequestOptions() {
        Request.Options options = new Request.Options(2000, TimeUnit.MILLISECONDS,
                2000, TimeUnit.MILLISECONDS,
                true);

        return  options;
    }

}

重啟,重新調用:

 

 看到配置已經生效了:

我們這里readTimeout 設置了2秒,如果我們在product服務睡眠3s看看:

product 服務沒有睡眠時,正常情況調用結果如下:

 

product 服務代碼修改:

 

 

 

 order 服務再次調用:

 

 可見,跟我們想象的一樣

如果feign的超時時間設置為4s,而hystrix的熔斷時間設置為2s看看:

 

 

 

 再次調用:

 

 重點是product服務的日志打印:

  證明order 服務熔斷了,但product 服務還是被調用了,說明feign的時間設置是沒問題的

根據上面分析,Hystrix的熔斷時間要大於Feign或Ribbon的connectTimeout+readTimeout

feign的超時時間如果要在application.yml中配置,改如何配置呢:

feign:
  hystrix:
    enabled: true
  client:
    config:
      default:
        #連接到目標的時間,此處會收到注冊中心啟動中的影響。設置為3秒鍾,如果注冊中心有明顯的不在線,基本是毫秒級熔斷拒絕
        connectTimeout: 3000
        #獲取目標連接后執行的最長時間,設置為32秒,即服務最長時
        readTimeout: 32000

為何能這樣配置呢?

 

 

 

  我們再次啟動order服務,調用跟蹤:

 

 那ribbon的超時時間如何配置:

ribbon:
  ReadTimeout: 3000
  ConnectTimeout: 3000

再次啟動測試:

 

 那么有人要問了,如果feign和ribbon同時配置,那么以誰的為准,前面已經分析過了,這里再次分析:

 

 重新調用跟蹤:

 

 

 

 繼續跟蹤:

 

 

 

 

 

 最后總結:

hystrix的熔斷時間配置通過yml配置沒法生效,可以通過配置類的方法來修改,feign的超時時間可以通過代碼或者yml配置,ribbon的超時時間可以通過yml來配置

feign和ribbon的超時時間只能二選一,只要feign的超時時間配置了,就以feign的為准,hystrix的超時時間要大於feign/riboon的connectTimeout+readTimeout的和

最后一張圖來總結:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

     

 


免責聲明!

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



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