開了hystrix 通過feign調不通服務的一次故障分析

開了hystrix 通過feign調不通服務的一次故障分析

一,微服務之間通過feign調用,本來都是正常走通的。在配置了hystrix 之後 就走不通了,只是有了個空指針異常

二,通過各種方式的查找,終於發現了問題的地方,代碼如下:

/**
 * Feign配置
 * 使用FeignClient進行服務間調用,傳遞headers信息
 */
@Configuration
public class FeignConfig implements RequestInterceptor {
    @Override
    public void apply(RequestTemplate requestTemplate) {
        ServletRequestAttributes attributes = null;
        if(RequestContextHolder.getRequestAttributes() instanceof ServletRequestAttributes){
            attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        }
        if(attributes != null){
            HttpServletRequest request = attributes.getRequest();
            Enumeration<String> headerNames = request.getHeaderNames();
            if (headerNames != null) {
                while (headerNames.hasMoreElements()) {
                    String name = headerNames.nextElement();
                    String values = request.getHeader(name);
                    requestTemplate.header(name, values);
                }
            }
        }
    }
}

現在的代碼,我已經做了判空的判斷。不過,這樣也是不合理的。正常情況不可能爲空,爲什麼會空指針異常?

三,又經過各種查找,百度,google。終於找到問題所在,配置代碼如下:

#開啓hystrix
feign:
  hystrix:
    enabled: true
#配置hystrix超時
hystrix:
  command:
    default:  #default全局有效,service id指定應用有效
      execution:
        timeout:
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 6000 #斷路器超時時間,默認1000ms
          strategy: SEMAPHORE
#配置ribbon超時
ribbon:
  OkToRetryOnAllOperations: false #對所有操作請求都進行重試,默認false
  ReadTimeout: 10000   #負載均衡超時時間,默認值5000  要比hystrix超時大 否則 觸發不了熔斷
  ConnectTimeout: 3000 #ribbon請求連接的超時時間,默認值2000
  MaxAutoRetries: 0     #對當前實例的重試次數,默認0
  MaxAutoRetriesNextServer: 1 #對切換實例的重試次數,默認1

我配置了hystrix,策略是thread,而獲取就不是同一個thread,所以出現了null。現在startegy被改成了SEMAPHORE,就暫時解決了這個問題。

四,官方不建議用SEMAPHORE這種隔離級別

可以自定義隔離級別 在繼承官方隔離基礎上,可以傳遞threadlocal

/**
 * 修改默認的hystrix隔離策略 使得可以傳遞content
 * @author liyouqing
 */
@Component
public class FeignHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

    private static final Logger log = LoggerFactory.getLogger(FeignHystrixConcurrencyStrategy.class);

    private HystrixConcurrencyStrategy delegate;

    public FeignHystrixConcurrencyStrategy() {
        try {
            this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
            if (this.delegate instanceof FeignHystrixConcurrencyStrategy) {
                // Welcome to singleton hell...
                return;
            }

            HystrixCommandExecutionHook commandExecutionHook =
                    HystrixPlugins.getInstance().getCommandExecutionHook();

            HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
            HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
            HystrixPropertiesStrategy propertiesStrategy =
                    HystrixPlugins.getInstance().getPropertiesStrategy();
            this.logCurrentStateOfHystrixPlugins(eventNotifier, metricsPublisher, propertiesStrategy);

            HystrixPlugins.reset();
            HystrixPlugins instance = HystrixPlugins.getInstance();
            instance.registerConcurrencyStrategy(this);
            instance.registerCommandExecutionHook(commandExecutionHook);
            instance.registerEventNotifier(eventNotifier);
            instance.registerMetricsPublisher(metricsPublisher);
            instance.registerPropertiesStrategy(propertiesStrategy);
        } catch (Exception e) {
            log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
        }
    }

    private void logCurrentStateOfHystrixPlugins(HystrixEventNotifier eventNotifier,
                                                 HystrixMetricsPublisher metricsPublisher,
                                                 HystrixPropertiesStrategy propertiesStrategy) {
        if (log.isDebugEnabled()) {
            log.debug("Current Hystrix plugins configuration is [" + "concurrencyStrategy ["
                    + this.delegate + "]," + "eventNotifier [" + eventNotifier + "]," + "metricPublisher ["
                    + metricsPublisher + "]," + "propertiesStrategy [" + propertiesStrategy + "]," + "]");
            log.debug("Registering Sleuth Hystrix Concurrency Strategy.");
        }
    }

    @Override
    public <T> Callable<T> wrapCallable(Callable<T> callable) {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return new WrappedCallable<>(callable, requestAttributes);
    }

    @Override
    public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
                                            HystrixProperty<Integer> corePoolSize,
                                            HystrixProperty<Integer> maximumPoolSize,
                                            HystrixProperty<Integer> keepAliveTime,
                                            TimeUnit unit, BlockingQueue<Runnable> workQueue) {
        return this.delegate.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime,
                unit, workQueue);
    }

    @Override
    public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,
                                            HystrixThreadPoolProperties threadPoolProperties) {
        return this.delegate.getThreadPool(threadPoolKey, threadPoolProperties);
    }

    @Override
    public BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {
        return this.delegate.getBlockingQueue(maxQueueSize);
    }

    @Override
    public <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {
        return this.delegate.getRequestVariable(rv);
    }

    static class WrappedCallable<T> implements Callable<T> {
        private final Callable<T> target;
        private final RequestAttributes requestAttributes;

        WrappedCallable(Callable<T> target, RequestAttributes requestAttributes) {
            this.target = target;
            this.requestAttributes = requestAttributes;
        }

        @Override
        public T call() throws Exception {
            try {
                RequestContextHolder.setRequestAttributes(requestAttributes);
                return target.call();
            } finally {
                RequestContextHolder.resetRequestAttributes();
            }
        }
    }
}
發佈了25 篇原創文章 · 獲贊 13 · 訪問量 3897
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章