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 许可协议。转载请注明来自 喵喵博客!


