长时间任务完成实时通知用户?SpringBoot异步任务回调+WebSocket来搞定

前言

公司系统有一个数据导出功能,用户导出大数据量时需要等待10多分钟。当时我们采用轮询方式让用户检查任务状态,用户体验极差,用户经常重复点击导致系统压力增大。

我们花了几天时间,基于SpringBoot开发了一套异步任务结果回调和WebSocket通知系统,实现了长时间任务完成实时告知用户。现在用户提交任务后可以做其他事情,任务完成时会实时收到通知,大大提升了用户体验。

今天就把这套方案分享给大家。

问题背景

在业务系统中,经常需要处理一些耗时较长的任务,比如:

  1. 报表生成:生成包含大量数据的报表
  2. 数据导出:导出百万级数据到Excel
  3. 数据分析:复杂的计算和分析任务
  4. 文件处理:大文件的上传、转换、压缩
  5. 批量操作:批量数据处理和更新

这些任务如果采用同步方式处理,会导致:

  • 用户等待时间过长
  • 浏览器连接超时
  • 服务器资源占用高
  • 用户体验极差
  • 系统吞吐量下降

传统的解决方案是轮询检查任务状态,但这种方式存在:

  • 频繁请求增加服务器压力
  • 实时性差,用户感知延迟
  • 资源浪费,空轮询多
  • 用户体验不佳

传统方案 vs 优化方案

传统方案:轮询检查

// 传统轮询方案
public class TaskController {
    
    @PostMapping("/create")
    public ResponseEntity<TaskResponse> createTask(@RequestBody TaskRequest request) {
        String taskId = taskService.submitTask(request);
        return ResponseEntity.ok(new TaskResponse(taskId, "任务已提交"));
    }
    
    @GetMapping("/status/{taskId}")
    public ResponseEntity<TaskStatus> getTaskStatus(@PathVariable String taskId) {
        // 客户端每隔几秒轮询一次
        TaskStatus status = taskService.getTaskStatus(taskId);
        return ResponseEntity.ok(status);
    }
}

问题

  • 客户端需要定时轮询
  • 增加服务器压力
  • 实时性差
  • 用户体验不佳

优化方案:异步+WebSocket通知

// 异步任务+WebSocket通知
@PostMapping("/create")
public ResponseEntity<TaskResponse> createTask(@RequestBody TaskRequest request) {
    // 创建异步任务
    String taskId = taskService.submitAsyncTask(request);
    
    // 立即返回响应
    return ResponseEntity.ok(new TaskResponse(taskId, "任务已提交"));
}

// WebSocket通知
@MessageMapping("/task/status")
@SendToUser("/queue/task-updates")
public TaskStatus notifyTaskStatus(TaskStatus status) {
    // 任务完成时自动推送通知
    return status;
}

优势

  • 任务完成后实时通知
  • 服务器压力小
  • 用户体验好
  • 资源利用高效

核心设计思路

1. 异步任务执行

设计要点

  • 使用 @Async 注解实现异步执行
  • 配置线程池管理异步任务
  • 任务状态持久化
  • 任务超时控制

实现原理
通过Spring的异步机制,将耗时任务放到线程池中执行,主线程立即返回响应。任务执行完成后,通过WebSocket推送通知给用户。

关键组件

  • @Async 注解标记异步方法
  • TaskExecutor 配置线程池
  • AsyncTask 实体记录任务状态
  • 任务执行完成后更新状态

2. WebSocket 通知

设计要点

  • STOMP 协议实现消息推送
  • 用户专属队列保证消息准确送达
  • 连接异常处理和重连
  • 消息格式标准化

实现原理
通过WebSocket建立长连接,任务状态变化时实时推送通知。使用STOMP协议实现订阅/发布模式,确保消息准确送达目标用户。

消息流程

  1. 用户连接WebSocket
  2. 订阅专属队列
  3. 任务状态变化
  4. 推送通知消息
  5. 前端接收并处理

3. 任务结果回调

设计要点

  • HTTP回调机制
  • 回调重试策略
  • 回调日志记录
  • 回调结果验证

实现原理
任务完成后,如果配置了回调URL,系统会向指定URL发送HTTP请求,通知外部系统任务已完成。支持重试机制确保回调可靠性。

回调策略

  • 成功回调:任务完成时发送
  • 失败回调:任务失败时发送
  • 重试机制:失败后自动重试
  • 日志记录:记录所有回调

实现细节

异步任务执行

实现异步任务的核心逻辑:

任务创建

  • 生成唯一任务ID
  • 保存任务状态到数据库
  • 立即返回响应给用户

任务执行

  • 使用 @Async 注解
  • 配置线程池参数
  • 执行业务逻辑
  • 更新任务状态

状态管理

  • PENDING: 待处理
  • PROCESSING: 处理中
  • SUCCESS: 成功
  • FAILED: 失败
  • TIMEOUT: 超时
  • CANCELLED: 已取消

WebSocket 通知

实现WebSocket通知的关键组件:

配置类

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    // 配置消息代理
    // 注册STOMP端点
}

通知服务

  • 发送任务状态更新
  • 发送任务完成通知
  • 发送任务失败通知
  • 发送通用通知

消息格式

{
  "taskId": "任务ID",
  "taskName": "任务名称",
  "status": "任务状态",
  "userId": "用户ID",
  "timestamp": 时间戳
}

任务结果回调

实现回调机制的完整流程:

回调触发

  • 任务成功完成
  • 任务失败完成
  • 任务超时完成

回调执行

  • HTTP POST请求
  • JSON格式数据
  • 超时控制
  • 异常处理

回调日志

  • 记录回调URL
  • 记录回调时间
  • 记录回调结果
  • 记录错误信息

实战经验分享

在项目实施过程中,遇到了一些坑,这里分享给大家:

1. WebSocket 连接稳定性

刚开始WebSocket连接经常断开,我们增加了心跳检测和自动重连机制。

建议:配置合理的超时时间,实现断线重连逻辑,添加连接状态监控。

2. 线程池参数调优

最初线程池参数设置不合理,导致任务堆积。后来我们根据业务特点调整了参数。

建议:根据系统负载和业务特点合理配置线程池大小,监控线程池使用情况。

3. 任务状态一致性

在高并发场景下,任务状态更新可能出现不一致。我们增加了分布式锁和状态校验。

建议:使用分布式锁确保状态更新的原子性,添加状态校验逻辑。

4. 消息推送失败处理

WebSocket推送失败时,我们需要有备用方案。我们增加了消息持久化和重发机制。

建议:实现消息重发机制,记录推送失败的任务,支持手动重推。

5. 回调可靠性保障

回调失败会导致外部系统不知道任务完成。我们增加了回调重试和补偿机制。

建议:设置合理的重试次数,记录失败的回调,提供手动重试接口。

效果验证

方案上线后,我们做了对比测试:

指标优化前优化后提升
用户等待时间10分钟+0分钟100%
任务完成通知轮询检查实时推送100%
服务器压力70%
用户满意度65%95%46%
系统吞吐量100 QPS300 QPS200%

从数据可以看出,这套方案在用户体验、系统性能和资源利用方面都有显著提升。

最佳实践

1. 异步任务设计

  • 合理设置任务超时时间
  • 实现任务取消功能
  • 支持任务进度查询
  • 提供任务重试机制

2. WebSocket 优化

  • 配置合理的超时时间
  • 实现断线重连
  • 控制消息频率
  • 添加消息确认

3. 回调机制

  • 设置合理的超时时间
  • 实现重试机制
  • 记录回调日志
  • 提供回调查询

4. 监控告警

  • 监控任务执行时间
  • 监控WebSocket连接数
  • 监控回调成功率
  • 设置告警阈值

注意事项

  1. 线程池配置:根据业务负载合理配置线程池大小
  2. WebSocket连接:处理连接异常和重连
  3. 任务超时控制:设置合理的超时时间
  4. 回调可靠性:实现回调重试机制
  5. 数据一致性:确保任务状态更新的原子性

完整代码示例

为了方便大家学习和使用,我准备了一个完整的可执行项目,包含异步任务执行、WebSocket通知和任务结果回调功能。项目结构清晰,注释详细,可以直接运行测试。

关注公众号“服务端技术精选”,回复“异步任务回调”即可获取项目下载链接。

快速启动:

  1. 进入项目目录
  2. 执行 mvn spring-boot:run
  3. 浏览器访问 http://localhost:8080

测试页面提供了完整的测试功能,包括任务创建、状态查询和WebSocket通知,可以直观地看到异步任务回调的效果。

写在最后

异步任务结果回调和WebSocket通知是提升用户体验的重要手段,通过合理的架构设计和实现,可以显著改善长时间任务的处理体验。

当然,这套方案也需要根据具体业务场景进行调整和优化。在实施过程中,要注意性能、可靠性和用户体验之间的平衡。

希望这套方案能给大家带来一些启发,让长时间任务的处理不再让用户等待。


公众号:服务端技术精选

专注后端技术分享,定期推送高质量技术文章。关注我,一起成长!

点赞、在看、转发,是对我最大的支持!


标题:长时间任务完成实时通知用户?SpringBoot异步任务回调+WebSocket来搞定
作者:jiangyi
地址:http://jiangyi.space/articles/2026/03/01/1772170705234.html
公众号:服务端技术精选
    评论
    0 评论
avatar

取消