版本 | 修订人 | 修订内容 | 修订日期 |
---|---|---|---|
V1.0 | 王旭 | 创建文档 | 2023-02-21 |
一、场景
新增建议场景管理员时,调用了授权的接口,接口是通过token获取的tanentId。
而Feign远程调用会丢失请求头导致报错:授权服务不可用。
二、原因及分析
1.进入feign远程调用的源码中
2.进入invoke方法 请求模板在executeAndDecode方法中被执行
3.Request在targetRequest被构建
4.通过遍历拦截器进行构建
5.SynchronousMethodHandler的构造方法私有 通过create方法创建
6.初始requestInterceptors为空 但加入了@RequestHeader spring通过CGLIB进行了增强
三、解决方法:
1.与上面一样 加入RequestHeader的Authorization属性 但每次远程调用都可能出现同样的问题
2.自定义拦截器,对远程调用进行增强,可以一次性解决问题
3.这样操作实际未生效,继续排查
四、排查未解决原因
原因及分析
1.打印主线程和拦截器中的线程号 发现不是同一个线程 推断每次远程调用都会创建新线程
2.RequestContextHolder内部的数据共享默认通过ThreadLocal来实现 故不同线程之间无法共享数据
3.通过查看配置文件 发现feign调用时启用了hystrix hystrix的隔离策略为Thread 每次远程调用会创建一个新线程
4.为了解决丢失上下文的问题 在远程调用前添加 保证在拦截器中能读取到
RequestContextHolder.setRequestAttributes(RequestContextHolder.currentRequestAttributes(),true);
RequestContextHolder中InheritableThreadLocal分析
https://www.jianshu.com/p/dffb197e2e53