FeignClient+Hystrix发起无法获取ServletRequest-经验总结

文章讲述了FeignClient在Hystrix线程隔离模式下遇到的问题,提出了解决方案:改用信号量隔离、通过RequestHeader传递header以及自定义Hystrix策略将header放入ThreadLocal。作者强调了信号量隔离的性能影响和线程安全特性。
摘要由CSDN通过智能技术生成

原因:feignclient转发会新启动一个线程,由于Hystrix隔离级别为线程级,context无法传递导致。

解决方案:

1,Hystrix隔离级别改为SEMAPHORE(信号量隔离策略)(官方不推荐) ->:

         execution.isolation.strategy:THREAD(SEMAPHORE)

        线程隔离策略涉及创建新线程,线程上下文切换,执行性能是低于信号量策略的。但是线程隔离策略完全隔离了依赖服务对当前的请求的影响,线程出现异常时不影响服务和其他请求,独立线程并发性高。线程隔离无法获取HTTPheader

        确保调用服务没有超时风险,可以考虑选择信号量隔离策略。

2,使用requestheader标签传递必须的header(适合少量) ->: 调用方和接收方接口需要明确参数

3,自定义Hystrix隔离隔离策略代码,将需要请求头放置于threadlocal中。(代码学习地址:feign 序列化_Spring Cloud(Feign+Hystrix)微服务之间参数传递-CSDN博客)->:

public class RequestAttributeHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

private static final Log log = LogFactory

.getLog(RequestAttributeHystrixConcurrencyStrategy.class);

private HystrixConcurrencyStrategy delegate;

public RequestAttributeHystrixConcurrencyStrategy() {

log.info("注入 Hystrix 熔断策略");

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 Callable wrapCallable(Callable callable) {

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

return new WrappedCallable<>(callable, requestAttributes);

}

@Override

public ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey,

HystrixProperty corePoolSize,

HystrixProperty maximumPoolSize,

HystrixProperty keepAliveTime, TimeUnit unit,

BlockingQueue 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 getBlockingQueue(int maxQueueSize) {

return this.delegate.getBlockingQueue(maxQueueSize);

}

@Override

public HystrixRequestVariable getRequestVariable(

HystrixRequestVariableLifecycle rv) {

return this.delegate.getRequestVariable(rv);

}

static class WrappedCallable implements Callable {

private final Callable target;

private final RequestAttributes requestAttributes;

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

}

}

}

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值