罗展丰
Published on 2026-06-12 / 19 Visits
0
0

任务模块架构设计

一、概述

Task 模块是一个通用的异步任务执行框架,采用工厂模式 + 策略模式设计,支持任务的异步执行、状态管理、结果持久化和分布式锁保护。核心能力包括:导入/导出任务处理、任务状态跟踪、失败重试、结果文件上传等。


二、核心架构

2.1 架构分层

┌─────────────────────────────────────────────────────────────────────┐
│                        Controller 层                               │
│   TaskController    TaskImportController    TaskExportController   │
└───────────────────────────┬─────────────────────────────────────────┘
                            │
              ┌─────────────┼─────────────┐
              ▼             ▼             ▼
    ┌────────────────┐ ┌──────────────┐ ┌───────────────────┐
    │  TaskService   │ │TaskInvokeService│ │  TaskAsyncService │
    │ (CRUD + 查询)   │ │  (任务编排)      │ │  (异步执行引擎)    │
    └────────┬───────┘ └──────┬────────┘ └─────────┬─────────┘
             │                │                    │
             ▼                │                    │
    ┌────────────────┐        │                    │
    │   TaskMapper   │        │                    │
    │  (数据库访问)    │        │                    │
    └────────┬───────┘        │                    │
             │                │                    │
             ▼                │                    │
    ┌────────────────┐        │                    │
    │   sys_task     │        │                    │
    │  (任务表)        │        │                    │
    └────────────────┘        │                    │
                              ▼                    │
                    ┌──────────────────┐            │
                    │ TaskHandlerFactory│◄─────────┘
                    │   (处理器工厂)      │
                    └──────────┬─────────┘
                               │
              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
       ┌───────────────┐ ┌───────────────┐ ┌───────────────┐
       │ImportHandler  │ │ExportHandler  │ │CustomHandler  │
       │ (导入处理器)    │ │ (导出处理器)    │ │ (自定义处理器)  │
       └───────────────┘ └───────────────┘ └───────────────┘

2.2 核心组件职责

组件 职责 说明
TaskController REST API 入口 任务创建、查询、状态查询、重试
TaskImportController 导入任务专用入口 文件上传 + 导入任务创建
TaskExportController 导出任务专用入口 导出结果下载
TaskService 任务数据管理 CRUD、分页查询、状态更新、Excel导出
TaskInvokeService 任务编排调度 创建任务记录、获取处理器、触发异步执行
TaskAsyncService 异步执行引擎 分布式锁、任务执行、结果处理、OSS上传
TaskHandlerFactory 处理器工厂 Spring启动时自动注册所有 ITaskHandler
ITaskHandler 任务处理器接口 定义任务类型和执行方法

三、任务实体设计

3.1 Task 实体结构

字段 类型 说明
id Long 任务主键
name String 任务名称
type String 任务类型(唯一标识,对应 handler)
tag String 任务标签(IMPORT/EXPORT/CUSTOM)
status String 任务状态(PENDING/RUNNING/SUCCESS/FAILED)
className String 数据类全限定名(导入入参/导出出参)
fileId String 关联文件ID(导入上传/导出结果)
param String 任务参数(JSON格式)
result String 执行结果(JSON格式或成功/失败计数)
errorMessage String 错误信息
errorStack String 异常堆栈
startTime Instant 开始时间
endTime Instant 结束时间
duration Long 执行时长(毫秒)

3.2 任务状态流转

PENDING (待执行)
    │
    └─→ RUNNING (执行中)
            │
     ┌─────┴─────┐
     ▼           ▼
SUCCESS      FAILED
(成功)        (失败)

四、任务处理器设计

4.1 处理器接口

public interface ITaskHandler {
    // 返回任务定义(类型、名称、类名、标签)
    TaskHandleDTO getTaskHandleDTO();

    // 执行任务
    Object execute(TaskExecuteDTO executeDTO);
}

4.2 抽象基类

框架提供两个抽象基类,封装通用逻辑:

基类 用途 自动设置
AbstractImportHandler 导入任务 taskTag = "IMPORT"
AbstractExportHandler 导出任务 taskTag = "EXPORT"

设计意图:通过模板方法模式,子类只需实现具体的 doImport() / doExport() 方法,无需关心任务注册、标签设置等通用逻辑。

4.3 处理器注册机制

// TaskHandlerFactory 构造函数自动扫描所有 ITaskHandler 实现
@Autowired
public TaskHandlerFactory(List<ITaskHandler> taskHandlers) {
    // 检测重复任务类型
    // 按 taskType 映射到 Map(大小写不敏感)
}

// 使用时通过类型获取处理器
ITaskHandler handler = taskHandlerFactory.getTaskHandler("dictImport");

五、异步执行引擎

5.1 执行流程

TaskInvokeService.createAndExecute()
        │
        ▼
┌─────────────────────────────┐
│ 1. 创建 Task 记录           │
│    status = PENDING         │
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 2. 获取处理器               │
│    ITaskHandler handler     │
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 3. 触发异步执行             │
│    executeTask() @Async     │
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 4. 抢占分布式锁             │
│    Redis setnx             │
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 5. 更新状态为 RUNNING       │
│    启动锁续期线程           │
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 6. 执行 handler.execute()   │
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 7. 处理结果(OSS上传)      │
│    更新状态为 SUCCESS/FAILED│
└───────────┬─────────────────┘
            │
            ▼
┌─────────────────────────────┐
│ 8. 清理资源(关闭线程池、   │
│    删除锁)                 │
└─────────────────────────────┘

5.2 分布式锁机制

机制 实现 说明
锁获取 CacheHelper.setnx(key, value, expire) 原子操作,保证只有一个节点获得锁
锁续期 ScheduledExecutorService.scheduleAtFixedRate() 每30秒续期一次,防止任务超时释放锁
锁过期 默认300秒 宕机场景下自动释放锁
宕机恢复 启动时检查 RUNNING 状态任务的锁是否存在 不存在则标记为 FAILED

六、导入/导出任务特殊处理

6.1 导入任务

// AbstractImportHandler.execute() 模板方法
public Object execute(TaskExecuteDTO executeDTO) {
    return doImport(executeDTO);  // 子类实现具体导入逻辑
}

导入流程:

  1. 前端上传 Excel 文件 → 保存到 OSS → 返回 fileId
  2. 创建导入任务,记录 fileId 和 className
  3. 异步执行时从 OSS 下载文件 → 解析 Excel → 调用业务导入逻辑
  4. 导入结果(含校验状态)生成 Excel → 上传 OSS → 更新 task.fileId

6.2 导出任务

// AbstractExportHandler.execute() 模板方法
public Object execute(TaskExecuteDTO executeDTO) {
    return doExport(executeDTO.getTaskParam());  // 子类实现具体导出逻辑
}

导出流程:

  1. 创建导出任务,记录查询参数
  2. 异步执行时根据参数查询数据 → 生成 Excel → 上传 OSS
  3. 前端通过任务 ID 下载结果文件

七、关键设计决策

  1. 工厂模式解耦 — 任务类型与处理器解耦,新增任务类型只需实现接口并注册为 Spring Bean
  2. 分布式锁保护 — 防止多节点重复执行同一任务,支持水平扩展
  3. 锁续期机制 — 长任务不会因锁过期被其他节点抢占
  4. 宕机恢复 — 启动时自动检测并修复宕机导致的异常状态任务
  5. 模板方法模式 — 导入/导出抽象基类封装通用逻辑,子类只需关注业务实现
  6. 内存流处理 — Excel 读写使用 ByteArrayOutputStream,不落地磁盘,提升性能

Comment