一、无异步线程得情况下feign远程调用:

0、登录拦截器:

@Component
public class LoginUserInterceptor implements HandlerInterceptor {
public static ThreadLocal<MemberResVo> loginUser = new ThreadLocal<>();
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //获取登录用户的键
MemberResVo attribute = (MemberResVo) request.getSession().getAttribute(AuthServerConstant.LONG_USER);
if (attribute!=null){
loginUser.set(attribute);
return true;
}else {
request.getSession().setAttribute("msg","请先进行登录!");
response.sendRedirect("http://auth.gulimall.com/login.html");
return false;
}
}
}

1、问题示例图:

解决方法:

import feign.RequestInterceptor;
import feign.RequestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; @Configuration
public class GuliFeignConfig {
//fegin过滤器
@Bean("requestInterceptor")
public RequestInterceptor requestInterceptor() {
return new RequestInterceptor() {
public void apply(RequestTemplate template) {
//上下文环境保持器,拿到刚进来这个请求包含的数据,而不会因为远程数据请求头被清除
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();//老的请求
if (request != null) {
//同步老的请求头中的数据,这里是获取cookie
String cookie = request.getHeader("Cookie");
template.header("Cookie", cookie);
}
}
};
}
}

二、异步情况下丢失上下文问题:

① 在同一线程下进行远程调用,即一连串调用的情况下OrederService通过远程调用先查找adress信息,再查找cart信息,则仅需配置GuliFeignConfig就够了

② 由于采用的异步任务,所以101、102线程在自己的线程中调用登录拦截器interceptor,而其实只有在72号线程中登陆拦截器才进行放行(有请求头数据),这就导致101、102的request为null

解决方式(高亮部分):从总线中获取request数据放入子线程中

@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {
@Autowired
MemberFeignService memberFeignService; @Autowired
CartFeginService cartFeginService; @Autowired
ThreadPoolExecutor executor; @Autowired
WmsFeignService wmsFeignService; /**
* 订单确认页返回的数据
* @return
*/
@Override
public OrderConfirmVo confirmOrder() throws ExecutionException, InterruptedException {
OrderConfirmVo confirmVo = new OrderConfirmVo();
MemberResVo memberResVo = LoginUserInterceptor.loginUser.get();
//从主线程中获得所有request数据
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); CompletableFuture<Void> getAddressFuture = CompletableFuture.runAsync(() -> {
//1、远程查询所有地址列表
RequestContextHolder.setRequestAttributes(requestAttributes);
List<MemberAddressVo> address = memberFeignService.getAddress(memberResVo.getId()); confirmVo.setAddress(address);
}, executor); //2、远程查询购物车所选的购物项,获得所有购物项数据
CompletableFuture<Void> cartFuture = CompletableFuture.runAsync(() -> {
//放入子线程中request数据
RequestContextHolder.setRequestAttributes(requestAttributes);
List<OrderItemVo> items = cartFeginService.getCurrentUserCartItems();
confirmVo.setItem(items);
}, executor).thenRunAsync(()->{
RequestContextHolder.setRequestAttributes(requestAttributes);
List<OrderItemVo> items = confirmVo.getItem();
List<Long> collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
//远程调用查询是否有库存
R hasStock = wmsFeignService.getSkusHasStock(collect);
//形成一个List集合,获取所有物品是否有货的情况
List<SkuStockVo> data = hasStock.getData(new TypeReference<List<SkuStockVo>>() {
});
if (data!=null){
//收集起来,Map<Long,Boolean> stocks;
Map<Long, Boolean> map = data.stream().collect(Collectors.toMap(SkuStockVo::getSkuId, SkuStockVo::getHasStock));
confirmVo.setStocks(map);
}
},executor);
//feign远程调用在调用之前会调用很多拦截器,因此远程调用会丢失很多请求头 //3、查询用户积分
Integer integration = memberResVo.getIntegration();
confirmVo.setIntegration(integration);
//其他数据自动计算 CompletableFuture.allOf(getAddressFuture,cartFuture).get();
return confirmVo;
} }

在微服务环境下,远程调用feign和异步线程存在请求数据丢失问题的更多相关文章

  1. 2流高手速成记(之八):基于Sentinel实现微服务体系下的限流与熔断

    我们接上回 上一篇中,我们进行了简要的微服务实现,也体会到了SpringCloudAlibaba的强大和神奇之处 我们仅改动了两个注释,其他全篇代码不变,原来的独立服务就被我们分为了provider和 ...

  2. 032 搭建搜索微服务01----向ElasticSearch中导入数据--通过Feign实现微服务之间的相互调用

    1.创建搜索服务 创建module: Pom文件: <?xml version="1.0" encoding="UTF-8"?> <proje ...

  3. 微服务架构 | 4.2 基于 Feign 与 OpenFeign 的服务接口调用

    目录 前言 1. OpenFeign 基本知识 1.1 Feign 是什么 1.2 Feign 的出现解决了什么问题 1.3 Feign 与 OpenFeign 的区别与对比 2. 在服务消费者端开启 ...

  4. 客户端远程调用Feign

    客户端远程调用 Feign 什么是Feign? Feign是 Netflix 公司开源的声明式HTTP客户端 Github : Feign 源码 为什么需要Feign? 原代码可读性不高 复杂的URL ...

  5. TOP100summit:【分享实录-华为】微服务场景下的性能提升最佳实践

    本篇文章内容来自2016年TOP100summit华为架构部资深架构师王启军的案例分享.编辑:Cynthia 王启军:华为架构部资深架构师.负责华为的云化.微服务架构推进落地,前后参与了华为手机祥云4 ...

  6. 微服务架构下分布式Session管理

    转载本文需注明出处:EAII企业架构创新研究院(微信号:eaworld),违者必究.如需加入微信群参与微课堂.架构设计与讨论直播请直接回复此公众号:“加群 姓名 公司 职位 微信号”. 一.应用架构变 ...

  7. SpringBoot微服务架构下的MVC模型总结

    SpringBoot微服务架构下的MVC模型产生的原因: 微服务概念改变着软件开发领域,传统的开源框架结构开发,由于其繁琐的配置流程 , 复杂的设置行为,为项目的开发增加了繁重的工作量,微服务致力于解 ...

  8. 微服务架构下分布式事务解决方案——阿里GTS

    1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...

  9. 微服务架构下分布式事务解决方案——阿里云GTS

    https://blog.csdn.net/jiangyu_gts/article/details/79470240 1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这 ...

  10. 微服务架构下 CI/CD 如何落地

    本文系云原生应用最佳实践杭州站活动演讲稿整理.杭州站活动邀请了 Apache APISIX 项目 VP 温铭.又拍云平台开发部高级工程师莫红波.蚂蚁金服技术专家王发康.有赞中间件开发工程师张超,分享云 ...

随机推荐

  1. Tomcat请求处理流程与源码浅析

    系列文章目录和关于我 一丶Connector 在tomcat中,Connector负责开启socket并且监听客户端请求,返回响应数据. 其中: Endpoint:tomcat中没有这个接口,只有Ab ...

  2. kafka消费者那些事儿

    前言 消息的消费一般有两种模式,推模式和拉模式.推模式是服务端主动将消息推送给消费者,而拉模式是消费者主动向服务端发起请求来拉取消息.kakfa采用的是拉模式,这样可以很好的控制消费速率.那么kafk ...

  3. 2023最新IntellJ IDEA诺依SpringCloud开发部署文档(保姆级别)

    目录 若依RuoYi v3.6.2部署文档 一.环境构建 二.模块描述 三.部署后端 1.下载到本地. 2.MySQL导入数据. 3.Nacos修改 (1)保证本地Nacos下载安装成功,修改本地Na ...

  4. 逍遥自在学C语言 | for循环详解

    前言 C语言中的循环结构时,for循环是最常用的一种.它允许重复执行一段代码,直到满足特定条件为止. 本文将详细介绍for循环的用法,并提供相关的可编译运行的C代码示例. 一.人物简介 第一位闪亮登场 ...

  5. 2023-06-11:redis中,如何在100个亿URL中快速判断某URL是否存在?

    2023-06-11:redis中,如何在100个亿URL中快速判断某URL是否存在? 答案2023-06-11: 传统数据结构的不足 当然有人会想,我直接将网页URL存入数据库进行查找不就好了,或者 ...

  6. x.ai还是OpenAI?埃隆·马斯克的AI帝国【2】

    上期内容咱们提到了埃隆马斯克的特斯拉是自动驾驶领域的领导者,大家可能近些年也都有从各类渠道听到过Tesla自动驾驶有关的新闻.不同于像包括Google子公司Waymo在内的大多数使用激光雷达来实现自动 ...

  7. h2database BTree 设计实现与查询优化思考

    h2database 是使用Java 编写的开源数据库,兼容ANSI-SQL89. 即实现了常规基于 BTree 的存储引擎,又支持日志结构存储引擎.功能非常丰富(死锁检测机制.事务特性.MVCC.运 ...

  8. asp登录认证,记录最后一次登录时间,写入数据库代码

    最近开发了一个船员招聘网的程序,但是由于部分功能需要配合ASP代码才能使用,所以就发现以前写的这个asp登录认证代码,今天就将他公布一下. <!--#include file="con ...

  9. JDBC的增删改-结果集的元数据-Class反射-JDBC查询封装

    一.使用JDBC批量添加 ​ 知识点复习: ​1.JDBC的六大步骤 (导入jar包, 加载驱动类,获取连接对象, 获取sql执行器.执行sql与并返回结果, 关闭数据库连接) 2.​封装了一个DBU ...

  10. java反序列化与反序列化

    java反序列化漏洞 JAVA反序列化漏洞是由于开发者重写了readObject方法,该readObject方法方法调用了别的方法,最终执行到了例如Transfrom方法的危险方法 java序列化过程 ...