在微服务环境下,远程调用feign和异步线程存在请求数据丢失问题
一、无异步线程得情况下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和异步线程存在请求数据丢失问题的更多相关文章
- 2流高手速成记(之八):基于Sentinel实现微服务体系下的限流与熔断
我们接上回 上一篇中,我们进行了简要的微服务实现,也体会到了SpringCloudAlibaba的强大和神奇之处 我们仅改动了两个注释,其他全篇代码不变,原来的独立服务就被我们分为了provider和 ...
- 032 搭建搜索微服务01----向ElasticSearch中导入数据--通过Feign实现微服务之间的相互调用
1.创建搜索服务 创建module: Pom文件: <?xml version="1.0" encoding="UTF-8"?> <proje ...
- 微服务架构 | 4.2 基于 Feign 与 OpenFeign 的服务接口调用
目录 前言 1. OpenFeign 基本知识 1.1 Feign 是什么 1.2 Feign 的出现解决了什么问题 1.3 Feign 与 OpenFeign 的区别与对比 2. 在服务消费者端开启 ...
- 客户端远程调用Feign
客户端远程调用 Feign 什么是Feign? Feign是 Netflix 公司开源的声明式HTTP客户端 Github : Feign 源码 为什么需要Feign? 原代码可读性不高 复杂的URL ...
- TOP100summit:【分享实录-华为】微服务场景下的性能提升最佳实践
本篇文章内容来自2016年TOP100summit华为架构部资深架构师王启军的案例分享.编辑:Cynthia 王启军:华为架构部资深架构师.负责华为的云化.微服务架构推进落地,前后参与了华为手机祥云4 ...
- 微服务架构下分布式Session管理
转载本文需注明出处:EAII企业架构创新研究院(微信号:eaworld),违者必究.如需加入微信群参与微课堂.架构设计与讨论直播请直接回复此公众号:“加群 姓名 公司 职位 微信号”. 一.应用架构变 ...
- SpringBoot微服务架构下的MVC模型总结
SpringBoot微服务架构下的MVC模型产生的原因: 微服务概念改变着软件开发领域,传统的开源框架结构开发,由于其繁琐的配置流程 , 复杂的设置行为,为项目的开发增加了繁重的工作量,微服务致力于解 ...
- 微服务架构下分布式事务解决方案——阿里GTS
1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这样可以降低开发难度.增强扩展性.便于敏捷开发.当前被越来越多的开发者推崇,很多互联网行业巨头.开源社区等都开始了微服务 ...
- 微服务架构下分布式事务解决方案——阿里云GTS
https://blog.csdn.net/jiangyu_gts/article/details/79470240 1 微服务的发展 微服务倡导将复杂的单体应用拆分为若干个功能简单.松耦合的服务,这 ...
- 微服务架构下 CI/CD 如何落地
本文系云原生应用最佳实践杭州站活动演讲稿整理.杭州站活动邀请了 Apache APISIX 项目 VP 温铭.又拍云平台开发部高级工程师莫红波.蚂蚁金服技术专家王发康.有赞中间件开发工程师张超,分享云 ...
随机推荐
- .NET 创建无边框的跨平台应用
.NET 创建无边框的跨平台应用 在创建了Photino应用程序以后我们发现它自带了一个标题栏,并且非常丑,我们现在要做的就是去掉这个很丑的自带标题栏,并且自定义一个更好看的,下面我们将用Masa B ...
- Firefox Quantum 向左,Google Chrome 向右
今天,又重新安装了一下 Firefox Quantum-68.0 (64 位),不同的是这一次安装的是国际中文版,而不是北京谋智火狐的版本. 北京谋智火狐 国际中文版 总的来说,有几点体验: 在 ht ...
- ensp 链路聚合
链路聚合(Link Aggregation) 指将多个物理端口汇聚在一起,形成一个逻辑端口,以实现出/入流量吞吐量在各成员端口的负荷分担,链路聚合在增加链路带宽.实现链路传输弹性和工程冗余等方面是 ...
- 4. JDK相关设置
恐惧是本能,行动是信仰(在此感谢尚硅谷宋红康老师的教程) 1. 项目的 JDK 设置 File-->Project Structure...-->Platform Settings --& ...
- 1、笔记本刷ubuntu,安装饥荒服务器
目录 笔记本刷ubuntu,安装饥荒服务器 一.准备 二.笔记本刷机 1.制作Ubuntu server U盘启动盘 2.刷机 3.设置电源不休眠 三.安装饥荒服务器 四.最后说下网络 笔记本刷ubu ...
- .Net Core 如何数据导出 Excel?(EPPlus->OfficeOpenXml 实现固定列和动态列导出)
〇.前言 对于将数据以 Excel 表格文件输出,还是比较常用的,也存在诸多情况,比如列固定或不固定.数据类型为 List<T>或 Json 对象等. 本文通过包 OfficeOpenXm ...
- 怎样优雅地增删查改(一):从0开始搭建Volo.Abp项目
@ 目录 项目介绍 模块化 由框架实现的 需要实现的 创建项目 创建业务模块 配置引用和依赖 配置DbContext 创建实体和Dto 配置AutoMapper 软件系统中数据库或者持久层的基本操作功 ...
- 零基础实现Java直播(一):集成
从泛娱乐的秀场直播,到直播带货潮流中的电商直播,直播已经成为2020年最热的应用技术之一,越来越多的产品希望加入直播功能.下面我们基于即构Express Video SDK,来分享如何从零实现线上直播 ...
- WinUI(WASDK)使用MediaPipe检查人体姿态关键点
前言 之前有用这个MediaPipe.NET .NET包装库搞了手势识别,丰富了稚晖君的ElectronBot机器人的第三方上位机软件的功能,MediaPipe作为谷歌开源的机器视觉库,功能很丰富了, ...
- Microsoft edge锁定在任务栏上,被修改主页360的解决方法
今天从桌面下边的任务栏打开Microsoft edge浏览器,突然发现主页被篡改为360导航了(生气!恶龙咆哮ooo 在桌面上是Microsoft edge,固定到任务栏就成为Microsoft ed ...