场景
公司有个报告导出的需求,但是报告导出的时间比较长,报告中查询的sql耗时较长,同时需要调用python脚本生成对应图片,过程长同时消耗的资源也比较大.
服务器使用的阿里云服务器,使用的域名也是阿里云的域名.
这样就会有个问题,阿里云的域名有个固定的限制,一个请求最长不能超过120秒,如果超过了120秒那么就会强制断开当前链接.
痛点: 由于强制断开的机制,请求报告的时候生成的过程时间耗时太长,经过测试一般情况下都在120秒以上,这还是在生成报告的时候使用了多线程的情况下,一开始没有使用多线程的情况,最长的时间有超过20分钟都没有生成对应报告的情况.
解决问题
解决思路: 前端首先调用一个接口,这个接口组装好参数,然后异步执行报告生成的代码,最后通过另外一个接口去获取当前报告的生成情况,异步调用的代码如下:
// 用于存储当前报告生成的状态
public static Map<String, ExportProjectCompleteVo> projectExportDoc = new HashMap<>();
public vo exportProjectComplete(Req req) {
vo vo = new vo();
String key = req.getProjectCode() + req.getStartDate() + req.getEndDate();
// 当前生成过,直接取对应的报告地址
if(ExportDocUtil.projectExportDoc.get(key) != null && ExportDocUtil.projectExportDoc.get(key).getWordPath() != null){
// 当天已经生成过报告了,直接下载即可
return ExportDocUtil.projectExportDoc.get(key);
}
vo.setKey(key);
ExportDocUtil.projectExportDoc.put(key,vo);
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 异步执行 下载
CompletableFuture.runAsync(() ->{
asyncExportProjectComplete(req);
},executorService);
// 组装返回信息
vo exportProjectComplete = new vo();
exportProjectComplete.setKey(key);
exportProjectComplete.setStatus(AsyncExportProjectEnum.START.getCode());
return exportProjectComplete;
}
asyncExportProjectComplete(req); 就似乎报告生成的具体代码,当前的接口请求完后会马上返回,开启一个新的接口去执行 asyncExportProjectComplete(req) 的代码,在生成代码的方法里去维护 projectExportDoc Map 的信息,然后新开一个接口,让前端携带我们调用异步方法之前生成的 key 去请求另外一个接口.
另外一个接口就去拿 projectExportDoc 的状态即可