3

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

 1 year ago
source link: https://www.cnblogs.com/lori/p/17150559.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

118538-20230224105553718-1402661761.png

使用ThreadLocal存储变量

public class NextHttpHeader {

	static final InheritableThreadLocal<Map<String, String>> inheritableThreadLocal = new InheritableThreadLocal<>();
	public static void set(String key, String val) {
		if (inheritableThreadLocal.get() == null) {
			inheritableThreadLocal.set(MapUtils.<String, String>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<String> get() {
		if (inheritableThreadLocal.get() == null) {
			return null;
		}
		return inheritableThreadLocal.get().keySet();
	}


}

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

public class RequestContextHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

	public <T> Callable<T> wrapCallable(Callable<T> callable) {
		// 先包装一下要执行的任务,在这里把ThreadLocal的值取出来
		return new ThreadLocalCallable<T>(callable);
	}

	public static class ThreadLocalCallable<V> implements Callable<V> {

		private Callable<V> target;

		private Map<String, String> dic = new HashMap<>();

		public ThreadLocalCallable(Callable<V> target) {
			this.target = target;
			NextHttpHeader.get().forEach(o -> {
				this.dic.put(o, NextHttpHeader.get(o));
			});
		}

		@Override
		public V call() throws Exception {
			this.dic.keySet().forEach(o -> {
				NextHttpHeader.set(o, this.dic.get(o));
			});
			return target.call();
		}

	}

}
@Configuration
@Slf4j
public class HystrixCircuitBreakerConfiguration {

	@PostConstruct
	public void init() {
		HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestContextHystrixConcurrencyStrategy());
	}

}

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

/**
 * 基于openFeign的拦截器,处理需要向下游传递的信息.
 *
 * @author lind
 * @date 2023/1/29 11:44
 * @since 1.0.0
 */
@Configuration
public class FeignTraceIdInterceptor implements RequestInterceptor {

	@Override
	public void apply(RequestTemplate template) {

		if (NextHttpHeader.get() != null) {
			NextHttpHeader.get().forEach(o -> {
				template.header(o, NextHttpHeader.get(o));
			});
		}
	}

}

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK