Skip to content

Commit 1aa3d20

Browse files
author
litongjava
committed
add tio-boot async task
1 parent c891f77 commit 1aa3d20

File tree

1 file changed

+124
-0
lines changed
  • docs/zh/05_web开发

1 file changed

+124
-0
lines changed

docs/zh/05_web开发/20.md

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# 异步 Controller
2+
3+
## 使用场景
4+
5+
大文件上传及上传后进行语音识别的应用场景
6+
7+
- 大文件上传: 企业员工上传完整的会议录音或录像文件
8+
- 上传后进行语音识别: 对会议内容进行自动转写,生成会议纪要,便于后续查阅和分析讨论点
9+
10+
如果上传完成后不采用异步任务对文件进行语音识别,可能会出现以下问题:
11+
12+
- 响应延迟: 语音识别是一个计算密集型的操作,特别是当处理大文件时。如果在同一请求中直接进行语音识别,服务器响应时间将大幅增加,导致用户体验变差。
13+
- 超时错误: 许多 Web 服务器和 HTTP 客户端都有请求超时的限制。长时间的同步处理可能导致请求超时,从而使得语音识别任务失败。
14+
- 资源占用: 大量的同步语音识别任务可能会占用大量服务器资源,包括 CPU 和内存,影响服务器处理其他请求的能力,降低整体服务的可用性和稳定性。
15+
- 用户界面冻结: 对于基于 Web 的应用,如果在前端直接等待语音识别的结果,可能导致用户界面冻结,无法进行其他操作,影响用户体验。
16+
17+
目前比较通用的做法是采用异步任务
18+
19+
1. 文件上传
20+
21+
- 用户通过客户端(如 Web 页面、移动应用)上传文件。
22+
- 服务器接收到文件后,存储在服务器上或云存储服务中,并立即返回一个响应告诉用户文件已成功上传。
23+
24+
2. 异步任务创建
25+
26+
- 在文件上传成功后,服务器不直接进行语音识别处理,而是创建一个异步任务。
27+
- 这个任务被发送到消息队列中,这样可以在系统资源允许的情况下按顺序或并行处理。
28+
29+
3. 任务处理
30+
31+
- 后台工作进程监听消息队列。一旦发现新任务,就开始处理该任务。
32+
- 在处理过程中,工作进程执行语音识别操作,将音频文件转写为文本。
33+
34+
4. 更新状态和通知
35+
36+
- 一旦异步任务完成,系统会更新任务的状态(例如,从“处理中”变为“已完成”)。
37+
- 系统可以通过不同的方式通知用户任务已完成,比如电子邮件通知、短信、应用内通知等。
38+
- 用户可以通过客户端查询任务状态,或者直接获取任务结果(如转写好的文本)。
39+
40+
## tio-boot 实现异步
41+
42+
- tio-boot 内置了线程池工具类 com.litongjava.tio.utils.thread.ThreadUtils
43+
44+
配置线程池
45+
46+
```
47+
package com.litongjava.apps.asrgpt.config;
48+
49+
import java.util.concurrent.ExecutorService;
50+
51+
import com.litongjava.jfinal.aop.annotation.AConfiguration;
52+
import com.litongjava.jfinal.aop.annotation.AInitialization;
53+
import com.litongjava.tio.boot.server.TioBootServer;
54+
import com.litongjava.tio.utils.thread.ThreadUtils;
55+
56+
@AConfiguration
57+
public class ExecutorServiceConfig {
58+
59+
@AInitialization
60+
public void config() {
61+
// 创建包含10个线程的线程池
62+
ExecutorService executor = ThreadUtils.newFixedThreadPool(10);
63+
64+
// 项目关闭时,关闭线程池
65+
TioBootServer.me().addDestroyMethod(() -> {
66+
if (executor != null && !executor.isShutdown()) {
67+
executor.shutdown();
68+
}
69+
});
70+
71+
}
72+
}
73+
74+
```
75+
76+
在 Controller 中使用线程池,开启异步任务
77+
78+
```
79+
import com.litongjava.apps.asrgpt.services.AsrSubmitService;
80+
import com.litongjava.apps.asrgpt.validator.AsrSubmitValidator;
81+
import com.litongjava.jfinal.aop.Aop;
82+
import com.litongjava.tio.http.common.HttpRequest;
83+
import com.litongjava.tio.http.common.HttpResponse;
84+
import com.litongjava.tio.http.common.UploadFile;
85+
import com.litongjava.tio.http.server.util.Resps;
86+
import com.litongjava.tio.utils.resp.RespVo;
87+
import com.litongjava.tio.utils.thread.ThreadUtils;
88+
89+
import lombok.extern.slf4j.Slf4j;
90+
91+
@Slf4j
92+
public class AsrSubmitController {
93+
94+
public HttpResponse submit(HttpRequest request) {
95+
UploadFile uploadFile = request.getUploadFile("file");
96+
String email = request.getParam("email");
97+
log.info("upload file size:{}", uploadFile.getData().length);
98+
log.info("email:{}", email);
99+
100+
//validator
101+
RespVo respVo = Aop.get(AsrSubmitValidator.class).submit(email);
102+
if (respVo != null) {
103+
return Resps.json(request, respVo);
104+
}
105+
106+
// 使用ExecutorService异步执行任务
107+
ThreadUtils.getFixedThreadPool().submit(() -> {
108+
try {
109+
RespVo result = Aop.get(AsrSubmitService.class).submit(uploadFile, email);
110+
// 在这里处理异步操作的结果,例如更新数据库或发送通知等
111+
log.info("异步任务执行完成, 结果: {}", result);
112+
} catch (Exception e) {
113+
log.error("异步任务执行异常", e);
114+
}
115+
});
116+
117+
// 立即响应客户端,表示文件上传请求已接收,正在处理中
118+
RespVo ok = RespVo.ok();
119+
ok.setMsg("文件上传成功,正在处理中...");
120+
return Resps.json(request, ok);
121+
}
122+
}
123+
124+
```

0 commit comments

Comments
 (0)