背景
假设我们有一个在线学习平台,管理员需要定期生成销售报告,包括课程销售情况和用户购买情况等重要数据。然而,由于数据量较大,生成报告可能需要较长时间,并且可能会占用大量系统资源,从而影响用户的使用体验。为了解决这个问题,我们考虑采用异步导出的方案。
异步导出的工作原理是将导出操作放在一个异步任务中执行,而不是立即在用户发起导出请求后执行导出操作。这样一来,用户无需等待导出任务完成,就可以继续进行其他操作,而系统则在后台完成导出任务。
这种方案有以下优点:
-
提高系统响应速度: 用户发起导出请求后,系统可以立即响应而不必等待导出任务完成,从而提高了系统的响应速度。
-
改善用户体验: 用户无需等待导出任务完成,可以继续使用系统进行其他操作,这有助于提升用户体验。
-
降低系统负载: 将耗时的导出操作放在异步任务中执行,可以避免阻塞系统资源,从而降低系统的负载,确保其他用户的操作不受影响。
异步导出在许多需要处理大量数据或耗时操作的场景中都非常有用,可以有效提升系统的性能和用户体验。
数据库设计
首先我们需要设计一个保存导出任务的表,需要记录流转状态、操作人、任务参数,后续任务的创建、导出完成/失败都需要操作这张表
CREATE TABLE `t_export_task`
(
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`task_id` varchar(50) NOT NULL COMMENT '任务id',
`task_type` tinyint(4) NOT NULL COMMENT '任务类型',
`task_param` varchar(1000) NOT NULL COMMENT '任务参数',
`status` tinyint(3) NOT NULL DEFAULT 0 COMMENT '状态 0-处理中 1-成功 -1失败',
`file_url` varchar(500) DEFAULT NULL COMMENT '文件url',
`remark` varchar(200) DEFAULT NULL COMMENT '备注',
`create_user_id` int(11) NOT NULL COMMENT '操作人id',
`create_user_name` varchar(50) NOT NULL COMMENT '操作人名称',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='导出任务记录';
代码实现
导出工具类 :
负责提交导出任务、取消任务以及上传导出文件到OSS服务器等功能。
-
导出任务线程池: 通过
ExecutorService
线程池来执行导出任务,并确保线程池的单例化,防止重复创建,提高性能。 -
导出类型对应的任务: 使用
Map<Integer, CompletableFuture<String>>
来保存正在运行的导出任务,以便后续取消任务或跟踪任务状态。 -
提交导出任务: 提交导出任务时,先初始化线程池,然后使用
CompletableFuture.supplyAsync()
方法执行异步任务,并在异步任务中生成导出文件,然后上传到OSS服务器,最后返回导出文件的URL。 -
取消任务: 取消任务时,从保存的任务映射中获取对应的
CompletableFuture
实例,并调用cancel()
方法取消任务。 -
上传文件到OSS服务器:
uploadToOS