记项目中的一次Excel导入优化

业务场景: 商家后台发货支持Excel批量发货设置,当excel数据过万时,会导致上传excel失败,主要的性能瓶颈是微服务架构下的请求超时,到聚合微服务解析完Excel数据传输到订单微服务时,由于数据过于庞大,订单微服务处理时间较长,导致请求超时失败

 

解决方案:

  1. 提高feign的超时配置
    ribbon:
      ReadTimeout: 30000
      ConnectTimeout: 30000  #解决feign.RetryableException

     

  2. 解析完Excel放入内存,分批次传给订单微服务

    private BatchDeliverGoodsResult BatchSendGoods(List list) {
            int size = list.size();
            int aBatch = size / BATCH_UNIT;
            List resultList = new ArrayList<>();
            for (int start = 0; start < aBatch; start++) {
                BatchDeliverGoodsResult batchResult = platformOrderFeignClient.batchDeliverGoods(list.subList(start * BATCH_UNIT, (start + 1) * BATCH_UNIT));
                resultList.add(batchResult);
            }
            if (aBatch * BATCH_UNIT < size) {
                BatchDeliverGoodsResult batchResult = platformOrderFeignClient.batchDeliverGoods(list.subList(aBatch * BATCH_UNIT, size));
                resultList.add(batchResult);
            }
            BatchDeliverGoodsResult result = new BatchDeliverGoodsResult();
            int failCount = resultList.stream().mapToInt(BatchDeliverGoodsResult::getFailCount).sum();
            int successCount = resultList.stream().mapToInt(BatchDeliverGoodsResult::getSuccessCount).sum();
            int total = resultList.stream().mapToInt(BatchDeliverGoodsResult::getTotal).sum();
            List> failList = new ArrayList<>();
            resultList.forEach(b -> {
                failList.addAll(b.getFailList());
            });
            result.setFailCount(failCount);
            result.setTotal(total);
            result.setSuccessCount(successCount);
            result.setFailList(failList);
            return result;
        }

     

  3. 使用@Async注解,实现请求异步化,为了避免商家重复上传excel.在redis中增加一个is:running的key,判断是否有值来决定是否进行数据解析操作,解析操作开始时删除redis中该店铺上次导入的结果,将第二步订单微服务的返回结果放入以shopId为key的redis内存,同时删除is:running key,只告知前端处理结果成功与否,前端也需配合修改页面用户交互逻辑,提供一个结果查询按钮,返回redis内存中该店铺刚导入的数据,若redis返回null,则表示该店铺没有导入结果或正在处理中

 

总结:

1.前端:上传成功后,前端固定提示:请求成功,请稍后查看导入结果。(前端不要主动调用查询结果接口,因为不知道这次任务要处理多久,给个查询按钮让用户自己点)
2.后端:导入任务开始时,清除上次导入结果。
3.后端:查询导入结果接口3种返回情况,<1>有数据返回数据 <2>无数据,有正在执行的导入任务,返回:导入任务正在执行中,请稍后查询。<3>无数据,无正在执行的导入任务,返回:请先执行导入操作。

你可能感兴趣的:(和光同尘)