最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Springcloud~openfeign开启hystrix基于线程池熔断的传值问题

来源:博客园


(相关资料图)

我们都知道,在hystrix默认情况下,采用线程池的熔断方式,每个openfeign都有自己的线程,而这使得它无法获取主线程上的变量;现在有个现实的问题就是,当前端登录后,把token经过gateway传到服务A,服务A再调用服务B时,B是无法收到请求头里的token信息的;一种不太好的解决方案就是使用信号量的方式。

使用ThreadLocal存储变量

public class NextHttpHeader {static final InheritableThreadLocal> inheritableThreadLocal = new InheritableThreadLocal<>();public static void set(String key, String val) {if (inheritableThreadLocal.get() == null) {inheritableThreadLocal.set(MapUtils.hashMapBuilder(8).put(key, val).build());} else {inheritableThreadLocal.get().put(key, val);}}public static String get(String key) {if (inheritableThreadLocal.get() == null) {return null;}return inheritableThreadLocal.get().get(key);}public static Set get() {if (inheritableThreadLocal.get() == null) {return null;}return inheritableThreadLocal.get().keySet();}}

继承HystrixConcurrencyStrategy抽象类,实现自己的赋值逻辑

public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {public  Callable wrapCallable(Callable callable) {// 先包装一下要执行的任务,在这里把ThreadLocal的值取出来return new ThreadLocalCallable(callable);}public static class ThreadLocalCallable implements Callable {private Callable target;private Map dic = new HashMap<>();public ThreadLocalCallable(Callable target) {this.target = target;NextHttpHeader.get().forEach(o -> {this.dic.put(o, NextHttpHeader.get(o));});}@Overridepublic V call() throws Exception {this.dic.keySet().forEach(o -> {NextHttpHeader.set(o, this.dic.get(o));});return target.call();}}}

注册

@Configuration@Slf4jpublic class HystrixCircuitBreakerConfiguration {@PostConstructpublic void init() {HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());}}

发现openFeign请求时,将变量放到请求头

/** * 基于openFeign的拦截器,处理需要向下游传递的信息. * * @author lind * @date 2023/1/29 11:44 * @since 1.0.0 */@Configurationpublic class FeignTraceIdInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate template) {if (NextHttpHeader.get() != null) {NextHttpHeader.get().forEach(o -> {template.header(o, NextHttpHeader.get(o));});}}}

spring中的口子太多,太灵活,需要不断的去找那个最优雅,最正确的方法

关键词: 解决方案 我们都知道 传递的信息