Feign Resilience4j 与 Hystrix 的碰撞
背景
在升级Springboot版本的时候,之前使用的是ContextHolder
threadLocal=ContextHolder.getInstance().getContextHolder(); |
获取一个map保存传递信息
原理是 使用Feign的拦截器
if(parMap!=null&&parMap.size()>0&&parMap.containsKey("Key")){ |
Feign的每次调用之前获取Key放到请求头上面
这种方法存在线程安全问题,需改造
-
引入依赖
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-bulkhead</artifactId>
</dependency> -
实现ContextPropagator
public class SeataPropagator implements ContextPropagator<String> {
public Supplier<Optional<String>> retrieve() {
return () -> Optional.ofNullable(RootContext.getXID());
}
public Consumer<Optional<String>> copy() {
return s -> s.ifPresent(RootContext::bind);
}
public Consumer<Optional<String>> clear() {
return s -> RootContext.unbind();
}
} -
添加配置
resilience4j:
thread-pool-bulkhead:
configs:
default:
context-propagators:
- cn.xxx.common.transaction.SeataPropagator
Q:为什么是使用新方法了而不是继续使用ContextHolder
A:ContextHolder使用TransmittableThreadLocal储存需要传递到下游的请求头,这在使用Hystrix或者不开启熔断器的时候有用
但当项目升级到使用Resilience4j作为熔断器之后,这种传递方式就不好用了,因为接入了 Resilience4j 熔断保护现在 Feign 调用使用了
Resilience4j 的线程来执行,导致 ThreadLocal.get(“Key”) 时值为 null,故无法把Val添加到 Feign Header 中
implements ContextPropagator
在copy方法里进行设置当前静态Context,Context可以获取到当前线程的保存的请求头参数,拷贝到Resilience4j线程中用来传递需要的信息
延展阅读
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 喵喵博客!