异步导入导出架构设计

时间:2024-01-23 08:48:24

 

为什么要用异步?

在我们平时的业务系统中,文件导入,文件导出是一个很常见的业务需求。正常情况下,同步导出就可以满足我们80%的需求。但是对于数据量大,业务拼接复杂的系统来说,导出超时,导入超时是不可避免的,而且是无法忍受的。异步能让业务线程在后台运行,没有等待时间,处理完成通知出来就行了。这种场景在现实生活中也很常见,比如医院里面拍CT,做体检时的体检报告,都是延后去拿结果的。

异步导出的使用场景

那什么时候会需要用到异步呢?统计、导入、导出、发送模板消息、订单状态变更后的复杂业务处理。。。 

它们都有共同的特点:

1.处理耗时长

2.业务优先级低

3.容易超时

4.数据量大

文件导出

异步导出的优缺点

异步的优点:

      它能解决导出超时问题,能大大的提高接口请求处理速度,提高吞吐量,提升系统性能

任何事情都有两面性,也许不具有绝对性,但是在这里是成立的。既然它有那么多优点,当然也会有缺点。

异步的缺点:

     它比同步导出要复杂得多,接口多了几倍,所需服务器也要多,学习成本高,开发成本高

架构图设计

 

 

架构解析

按流程来:

1.前端发出导出请求

2.接口服务器接到请求并校验参数

3.如果参数不符,直接弹出校验结果,流程结束!

4.生成一个任务实体,状态设为处理中并将实体写入redis。开启异步线程,在异步方法中调用导出接口。返回给前端在处理中状态

5.前端接受到已经在处理中返回值,开启ajax轮询,每隔10秒请求一次任务查询状态接口

6.导出接口将数据拼接完成

7.将数据传到文件服务器生成文件并返回url

8.从redis中取出任务实体将url写入,并且将状态设为已完成并更新redis(后端处理流程就结束了)

9.前端ajax请求发现返回值状态变成已完成后,取出url并停止轮询。

10.前端请求清除任务实体接口,通过后端接口将redis中的对象移除。

11.前端展示导出结果,自动下载或者手动点击可以根据业务来。

 

 

这里还有一个页面初始化的按钮变化流程。

1.打开页面后导出按钮置灰不可点击

2.ajax请求查询任务状态接口,如果显示没有任务在进行中,那就让导出按钮可以点击。如果状态是导出已完成,则显示下载按钮相关页面

数据来源

 

接口设计

 接口列表

       1.获取任务状态 getTaskStatus     

              返回实体TaskResultOut:


字段 l类型 是否可为空 注释
 
status
 int  不,默认0  任务状态(0=未开始,1=进行中 2=已完成)
 message  string  是  提示信息(正确或错误)
 url  string  是  文件地址
 state  bool  不,默认fasle  任务成功还是失败(y)

                         


  

 

 

2.注册导出任务(导出) registerExportTask

          返回true/false,表明是否注册成功

       3.清除任务状态 clearTaskInfo

          返回true/fasle,表明清除是否成功


前端设计

前端js由前端编写,具体的由于嵌套太深,就不贴出来了,在架构解析中已经说的很详细了。

"export": function(e) {
return t.post(r.api.form["export"], e, {})
},
getTaskStatus: function(e) {
return t.post(r.api.form.getTaskStatus, e, {})
},
registerExportTask: function(e) {
return t.post(r.api.form.registerExportTask, e, {})
},
clearTaskInfo: function(e) {
return t.post(r.api.form.clearTaskInfo, e, {})
}

 

项目实际应用

 

 点击取消后

 

 

 

异步导出的整个流程和设计就全在这里了。

文件导入的设计

由于篇幅有限,且导入的流程大同小异。之间奉上一副设计图吧。

多级异步导入方案

 

 

最后

代码是没有滴,东西是要自己创造滴!