解决在微服务环境下远程调用feign和异步线程存在请求数据丢失问题

网友投稿 1047 2022-10-03

解决在微服务环境下远程调用feign和异步线程存在请求数据丢失问题

解决在微服务环境下远程调用feign和异步线程存在请求数据丢失问题

目录一、无异步线程得情况下feign远程调用:1、登录-:2.问题示例图:3.解决方法:解决方式(高亮部分):从总线中获取request数据放入子线程中二、异步情况下丢失上下文问题:

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

1、登录-:

@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;

}

}

}

2.问题示例图:

3.解决方法:

import feign.RequestInterceptor;

import feign.RequestTemplate;

import org.springframework.context.annotation.Bean;http://

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数据放入子线程中

RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes()

@Service("orderService")

public class OrderServiceImpl extends ServiceImpl

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 getAddressFuture = CompletableFuture.runAsync(() -> {

//1、远程查询所有地址列表

RequestContextHolder.setRequestAttributes(requestAttributes);

List address = memberFeignService.getAddress(memberResVo.getId());

confirmVo.setAddress(address);

}, executor);

//2、远程查询购物车所选的购物项,获得所有购物项数据

CompletableFuture cartFuture = CompletableFuture.runAsync(() -> {

//放入子线程中request数据

RequestContextHolder.setRequestAttributes(requestAttributes);

ZrVdb List items = cartFeginService.getCurrentUserCartItems();

confirmVo.setItem(items);

}, executor).thenRunAsync(()->{

RequestContextHolder.setRequestAttributes(requestAttributes);

List items = confirmVo.getItem();

List collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());

//远程调用查询是否有库存

R hasStock = wmsFeignService.getSkusHasStock(collect);

//形成一个List集合,获取所有物品是否有货的情况

List data = hasStock.getData(new TypeReference>() {

});

if (data!=null){

//收集起来,Map stocks;

Map 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;

}

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:小程序提交审核要几天?(小程序审核时长)
下一篇:HDU 4908 BestCoder Sequence (哈希)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~