spring cloud feign在使用过程中可能会遇到的问题总结

1,默认不开启,开启hystrix熔断器后,发现下游服务器并没有问题,但是一直走熔断降级方法

# To disable Hystrix in Feign
feign:
  hystrix:
    enabled: true

解决方法

首先把Hystrix 在配置文件中的配置全部注释掉

server:
  port: 80
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:9999/eureka/
    #表示多久去注册中心拉取一次服务信息
    registry-fetch-interval-seconds: 30
    fetch-registry: true
    #Eureka客户端向服务端发送心跳时间的间隔,单位为秒(默认是30秒)
  instance:
    #向注册中心发起心跳
    lease-renewal-interval-in-seconds: 1

spring:
  application:
    name: user-consumers

user-providers:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
    ConnectTimeout: 10000 # 连接超时时间
    ReadTimeout: 10000 # 数据读取超时时间,连接之后,数据传输过程
    MaxAutoRetries: 1 # 最大重试次数(第一个服务)
    MaxAutoRetriesNextServer: 1 # 最大重试下一个服务次数(集群的情况才会用到)
    OkToRetryOnAllOperations: false # 是否对所有的请求都重试
    eager-load:
      enabled: true

logging:
  level:
    com.angen.controller: debug

#默认是ZoneAvoidanceRule
#service-provider-user这个是对应的微服务的名字
#
#service-provider-user:
#  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

#hystrix:
#  command:
#    default:
#      circuitBreaker:
#        #强制打开熔断器,默认是false
#        forceOpen: true
#        #触发熔断错误比例阈值,默认是50%
#        errorThresholdPercentage: 50
#        #熔断后休眠时长,默认是5000毫秒
#        sleepWindowInMilliseconds: 10000
#        #熔断触发最小请求次数,默认值是20
#        requestVolumeThreshold: 10
#      execution:
#        isolation:
#          #strategy: SEMAPHORE
#          thread:
#            #熔断超时设置,默认是1000毫秒
#            timeoutInMilliseconds: 10000

# To disable Hystrix in Feign
feign:
  hystrix:
    enabled: true
  httpclient:
    connection-timeout: 10000
  client:
    config:
      default:
        #连接到目标的时间,此处会收到注册中心启动中的影响。设置为3秒钟,如果注册中心有明显的不在线,基本是毫秒级熔断拒绝
        connectTimeout: 3000
        #获取目标连接后执行的最长时间,设置为32秒,即服务最长时
        readTimeout: 32000

然后自己定义配置文件

package com.angen.config;

import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import feign.Feign;
import feign.Target;
import feign.hystrix.SetterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.lang.reflect.Method;


@Configuration
public class FeignSupportConfig {
    @Bean
    public SetterFactory setterFactory(){
        SetterFactory setterFactory =new SetterFactory() {
            @Override
            public HystrixCommand.Setter create(Target<?> target, Method method) {

                String groupKey = target.name();
                String commandKey = Feign.configKey(target.type(), method);

                HystrixCommandProperties.Setter setter = HystrixCommandProperties.Setter()
                        //设置统计指标60秒为一个时间窗口
                        .withMetricsRollingStatisticalWindowInMilliseconds(1000 * 60)
                        //超过80%失败率
                        .withCircuitBreakerErrorThresholdPercentage(80)
                        //操作5个开启短路器
                        .withCircuitBreakerRequestVolumeThreshold(5)
                        //设置线程隔离
                        .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                        //设置断路器的开启时间为60秒
                        .withCircuitBreakerSleepWindowInMilliseconds(1000 * 60);

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

}

然后

重写一下HystrixConcurrencyStrategy 

原因大家可以看以下这个文章

Feign开启HyStrix后如何配置线程隔离及熔断策略_问题不太大的博客-CSDN博客_feign hystrix自定义隔离

开启hystrix:feign.hystrix.enabled=true时, RequestContextHolder.getRequestAttributes()为空_aresdata的博客-CSDN博客_feign.hystrix.enabled 

package com.angen.feign;

import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.strategy.HystrixPlugins;
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariable;
import com.netflix.hystrix.strategy.concurrency.HystrixRequestVariableLifecycle;
import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
import com.netflix.hystrix.strategy.properties.HystrixProperty;
import org.apache.commons.logging.Log;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


@Component
public class RequestAttributeHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {
    private static final Log log = LogFactory.getLog(RequestAttributeHystrixConcurrencyStrategy.class);

    private HystrixConcurrencyStrategy delegate;

    public RequestAttributeHystrixConcurrencyStrategy() {
        try {
            this.delegate = HystrixPlugins.getInstance().getConcurrencyStrategy();
            if (this.delegate instanceof RequestAttributeHystrixConcurrencyStrategy) {
                // 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.getInstance().registerConcurrencyStrategy(this);
            HystrixPlugins.getInstance()
                    .registerCommandExecutionHook(commandExecutionHook);
            HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
            HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
            HystrixPlugins.getInstance().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;

        public 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();
            }
        }
    }
}

如果这样还不生效配置,那么

还得在feign接口上载入配置文件configuration = FeignSupportConfig.class

@FeignClient(name = "user-providers",
        fallback = UserFeignImpl.class,
        path = "/user",
        configuration = FeignSupportConfig.class)
public interface UserFeign {
    /*
    * 这个路径对应请求微服务的路径
    * */
    @RequestMapping(method = RequestMethod.GET,value = "/{id}")
    public User feignFindById(@PathVariable("id") Integer id);
}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值