Fegin异步情况丢失上下文问题

在微服务的开发中,我们经常需要服务之间的调用,并且为了提高效率使用异步的方式进行服务之间的调用,在这种异步的调用情况下会有一个严重的问题,丢失上文下

通过以上图片可以看出异步丢失上下文的原因是不在同一个线程,所有数据不能共享,Wie了解决这个问题,我们就需要把之前线程的请求头上下文,在次存放到其他线程的请求头上下文就行,具体实现如下:

案例:feign异步获取订单明细的案例代码

复制代码
/**
     * 获取订单明细的vo
     * @return
     */
    @Override
    public OrderConfirmVo orderConfirm() {
        MemberResponseVo member = OrderInterceptor.threadLocal.get();

        OrderConfirmVo orderConfirmVo = new OrderConfirmVo();
        System.out.println("主线程:"+ Thread.currentThread().getId());
        //获取主线程的请求头信息
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();

        //考虑到效率问题  使用异步编排
        CompletableFuture<Void> getAddress = CompletableFuture.runAsync(() -> {
            //子线程中设置添加主线程的请求头信息  信息共享  否则远程调用异步处理丢失请求头信息
            RequestContextHolder.setRequestAttributes(requestAttributes);
            System.out.println("address:"+ Thread.currentThread().getId());
            //远程获取地址信息
            List<MemberAddressVo> address = memberFeignService.getAddress(member.getId());
            orderConfirmVo.setAddress(address);
        }, executor);


        CompletableFuture<Void> getItem = CompletableFuture.runAsync(() -> {
            //子线程中设置添加主线程的请求头信息  信息共享  否则远程调用异步处理丢失请求头信息
            RequestContextHolder.setRequestAttributes(requestAttributes);
            System.out.println("item:"+ Thread.currentThread().getId());
            //远程获取购物项
            List<OrderItemVo> currentUserCartItems = cartFeignService.getCurrentUserCartItems();
            orderConfirmVo.setItems(currentUserCartItems);
        }, executor).thenRunAsync(()->{
            List<OrderItemVo> items = orderConfirmVo.getItems();
            //获取所有商品的id
            List<String> collect = items.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
            List<Long> skuIds = collect.stream().map(item -> {
                return Long.parseLong(item);
            }).collect(Collectors.toList());
            R<List<SkuHasStockVo>> skusHasStock = wmsFeignService.getSkusHasStock(skuIds);
            List<SkuHasStockVo> data = skusHasStock.getData(new TypeReference<List<SkuHasStockVo>>() {
            });
            if(data!= null){
                Map<Long, Boolean> collect1 = data.stream().collect(Collectors.toMap(SkuHasStockVo::getSkuId, SkuHasStockVo::getHasStock));
                orderConfirmVo.setStocks(collect1);
            }
        },executor);

        //异步编排完成之后执行后续操作
        try {
            CompletableFuture.allOf(getAddress,getItem).get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }


        orderConfirmVo.setIntegration(member.getIntegration());

        orderConfirmVo.setPayPrice(orderConfirmVo.getPayPrice());
        orderConfirmVo.setTotal(orderConfirmVo.getTotal());
        //TODO 放重处理  生成token令牌储存在redis
        String token = UUID.randomUUID().toString().replace("-", "");
        orderConfirmVo.setOrderToken(token);
        redisTemplate.opsForValue().set(OrderConstant.ORDER_TOKEN+member.getId(),token);

        return orderConfirmVo;
    }
相关推荐
January12072 分钟前
IDEA 快捷键
java·ide·intellij-idea
周杰伦fans6 分钟前
C# 异常继承深度解析:从设计原则到 sealed 关键字的奥秘
java·jvm·c#
搬石头的马农7 分钟前
从零配置Claude自动修Bug:6步打造全自动开发流程
java·人工智能·python·bug·ai编程
小马爱打代码14 分钟前
Redis Key 过期后会立刻删除吗?过期删除与内存淘汰策略详解
java·redis·缓存
鱼鳞_21 分钟前
苍穹外卖-Day10(Spring task)
java·后端·spring
雨落在了我的手上30 分钟前
初始java(十七):常⽤⼯具类介绍
java·开发语言
凤凰院凶涛QAQ40 分钟前
《Java版数据结构 & 集合类剖析》集合框架的封装设计与顺序表:“从 Iterable 到 ArrayList:集合框架的‘职业树“
java·开发语言·数据结构
孟华苏1 小时前
怎么快速排查内存泄漏问题
java·开发语言·python
noipp1 小时前
推荐题目:洛谷 P16510 [GKS 2015 #C] gRanks
java·c语言·开发语言·c++·python·算法
flyinmind1 小时前
Java环境与Android环境中使用QuickJS
java·开发语言·javascript·quickjs