概述
大家好,我是不才陈某~
这是《Spring Cloud 进阶》第27篇文章,往期文章如下:
五十五张图告诉你微服务的灵魂摆渡者Nacos究竟有多强?
openFeign夺命连环9问,这谁受得了?
阿里面试这样问:Nacos、Apollo、Config配置中心如何选型?这10个维度告诉你!
阿里面试败北:5种微服务注册中心如何选型?这几个维度告诉你!
阿里限流神器Sentinel夺命连环 17 问?
对比7种分布式事务方案,还是偏爱阿里开源的Seata,真香!(原理+实战)
Spring Cloud Gateway夺命连环10问?
Spring Cloud Gateway 整合阿里 Sentinel网关限流实战!
分布式链路追踪之Spring Cloud Sleuth夺命连环9问?
链路追踪自从用了SkyWalking,睡的真香!
3本书了,7万+字,10篇文章,《Spring Cloud 进阶》基础版 PDF
妹子始终没搞懂OAuth2.0,今天整合Spring Cloud Security 一次说明白!
OAuth2.0实战!使用JWT令牌认证!
OAuth2.0实战!玩转认证、资源服务异常自定义这些骚操作!
实战干货!Spring Cloud Gateway 整合 OAuth2.0 实现分布式统一认证授权!
字节面试这样问:跨库多表存在大量数据依赖问题有哪些解决方案?
实战!退出登录时如何借助外力使JWT令牌失效?
实战!Spring Cloud Gateway集成 RBAC 权限模型实现动态权限控制!
实战!阿里神器 Seata 实现 TCC模式 解决分布式事务,真香!
实战!openFeign如何实现全链路JWT令牌信息不丢失?
微服务下蓝绿发布、滚动发布、灰度发布等方案,必须懂!
微服务如何聚合 API 文档?这波秀~
Spring Cloud 2021.0.1 正式发布,卷不动了~
实战!微服务 认证中心 如何扩展授权模式 实现多种方式登录?
Spring Cloud 再爆高危漏洞.... 赶紧修复!!
Spring Cloud Gateway 网关如何实现灰度发布?
最近有读者问了这样一个问题:陈哥,openFeign异步调用总是失败触发Sentinel的降级,同步调用就没问题?
他还给我晒了一下代码,大致如下:
CompletableFuture<T> future1 = CompletableFuture.supplyAsync(() -> {
//openfeign的调用
return feign.remoteCall();
},executor);
CompletableFuture<T> future2 = CompletableFuture.supplyAsync(() -> {
//openfeign的调用
return feign.remoteCall();
},executor);
CompletableFuture.allOf(future1,future2).join();
.....
这种情况你遇到过吗?
如何解决?
这个算是常见问题了:feign的调用导致上下文丢失;前面有一篇文章说过这种问题:实战!openFeign如何实现全链路JWT令牌信息不丢失?
在集成OAuth2的时候如果做任何设置会丢失令牌信息,当时我们的解决方案是新建一个拦截器,如下:
@Component
@Slf4j
public class FeignRequestInterceptor implements RequestInterceptor {
@Override
public void apply(RequestTemplate template) {
HttpServletRequest httpServletRequest = RequestContextUtils.getRequest();
Map<String, String> headers = getHeaders(httpServletRequest);
for (Map.Entry<String, String> entry : headers.entrySet()) {
template.header(entry.getKey(), entry.getValue());
}
}
/**
* 获取原请求头
*/
private Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> map = new LinkedHashMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
if (StrUtil.equals(OAuthConstant.TOKEN_NAME,key)){
map.put(key, value);
break;
}
}
}
return map;
}
}
上述代码根本逻辑就是将请求头中Token信息放入RequestTemplate的头中。
“注意:这里取出请求头中信息用的是RequestContextHolder。
”
看到这里是不是明白了,RequestContextHolder中是将请求信息放入ThreadLocal中的,只能取到同一个线程的数据。
因此要解决异步调用的问题,只需要在发起远程调用之前给异步线程添加上主线程的上下文信息,此时最上方调用失效的代码变成如下:
//获取主线程的请求信息
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
CompletableFuture<T> future1 = CompletableFuture.supplyAsync(() -> {
//将主线程的请求信息设置到异步线程中,否则会丢失请求上下文,导致调用失败
RequestContextHolder.setRequestAttributes(attributes);
//openfeign的调用
return feign.remoteCall();
},executor);
CompletableFuture<T> future2 = CompletableFuture.supplyAsync(() -> {
//将主线程的请求信息设置到异步线程中,否则会丢失请求上下文,导致调用失败
RequestContextHolder.setRequestAttributes(attributes);
//openfeign的调用
return feign.remoteCall();
},executor);
CompletableFuture.allOf(future1,future2).join();
.....
最后说一句(别白嫖,求关注)
陈某每一篇文章都是精心输出,已经写了3个专栏,整理成PDF,获取方式如下:
《Spring Cloud 进阶》PDF:关注公众号:【码猿技术专栏】回复关键词 Spring Cloud 进阶 获取!
《Spring Boot 进阶》PDF:关注公众号:【码猿技术专栏】回复关键词 Spring Boot进阶 获取!
《Mybatis 进阶》PDF:关注公众号:【码猿技术专栏】回复关键词 Mybatis 进阶 获取!
如果这篇文章对你有所帮助,或者有所启发的话,帮忙点赞、在看、转发、收藏,你的支持就是我坚持下去的最大动力!
关注公众号:【码猿技术专栏】,公众号内有超赞的粉丝福利,回复:加群,可以加入技术讨论群,和大家一起讨论技术,吹牛逼!
求点赞、在看、分享三连
最后
以上就是大意蜡烛为你收集整理的openFeign 异步 调用丢失上下文怎么破?的全部内容,希望文章能够帮你解决openFeign 异步 调用丢失上下文怎么破?所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复