SpringBoot 异步请求使用
·
文章目录
前言
本篇文章介绍异步请求
一、概述
1.1 什么是异步请求
异步请求是一种非阻塞的处理模式,客户端发起请求后,服务器立即返回而不等待业务逻辑完成,实际的处理在后台执行,完成后通过回调或其他机制通知客户端。
1.2 为什么要用异步请求
提高系统吞吐量和并发处理能力,假设我们有100个 tomcat I/O 线程,我们现在有一个需求:需要等待30s后再响应给前端,如果没用异步请求那这个接口一旦被频繁调用,会导致系统直接卡死,无法处理任何业务
如果使用了异步请求不阻塞 tomcat 的 I/O 线程,由少量线程处理大量的等待请求,一旦到期(超时),立即响应。
二、使用方式
2.1 原生方式
/**
* 使用 request 开启异步处理, 这种方式其实是 Servlet 的处理模式, springmvc 与 springboot 不推荐
* 如果使用这个只能返回 void, 如果返回别的, springMVC 会关闭 response
*/
@GetMapping("/servlet")
public void t2(HttpServletRequest request, HttpServletResponse response) throws IOException {
// 表示我们要开启异步请求了
AsyncContext asyncContext = request.startAsync();
// 设置 60s 超时时间
asyncContext.setTimeout(60_000);
asyncContext.start(() -> {
try {
// 模拟耗时操作
Thread.sleep(3000);
asyncContext.getResponse().getWriter().write("异步任务完成\n");
response.getWriter().flush();
// 异步处理完成
asyncContext.complete();
} catch (Exception e) {
System.out.println("异常");
}
});
response.setContentType("text/plain;charset=utf8");
response.getWriter().write("主线程完成\n");
response.getWriter().flush();
}
2.2 DeferredResult
@GetMapping("/deferred")
public DeferredResult<String> t1() {
DeferredResult<String> deferredResult = new DeferredResult<>();
log.info("defer-1");
// 模拟耗时操作,例如数据库查询或远程服务调用
new Thread(() -> {
try {
Thread.sleep(3000); // 模拟耗时操作
log.info("defer-2");
deferredResult.setResult("DeferredResult 任务完成"); // 设置结果
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 恢复中断状态
}
}).start();
return deferredResult;
}
2.3 CompletableFuture
@GetMapping("/waitMethod2")
public CompletableFuture<String> waitMethod2(String id) {
CompletableFuture<String> waitingFuture = new CompletableFuture<>();
CompletableFuture<String> timeoutFuture = CompletableFuture
.supplyAsync(() -> "超时返回",
CompletableFuture.delayedExecutor(30, TimeUnit.SECONDS));
waitingRequests2Map.put(id, waitingFuture);
return waitingFuture.applyToEither(timeoutFuture, Function.identity())
.whenComplete((result, throwable) -> {
waitingRequests2Map.remove(id);
if (!waitingFuture.isDone()) waitingFuture.cancel(false);
if (!timeoutFuture.isDone()) timeoutFuture.cancel(false);
});
}
2.4 Callable
@GetMapping("/callable")
public Callable<String> callable() {
return () -> {
// 模拟耗时操作
Thread.sleep(3000);
return "Callable 线程任务完成";
};
}
2.5 WebAsyncTask
@GetMapping("/webAsyncTask")
public WebAsyncTask<String> webAsyncTask() {
return new WebAsyncTask<>(3000, () -> {
// 模拟耗时操作
Thread.sleep(3000);
return "WebAsyncTask 线程任务完成";
});
}
三、使用异步请求处理等待30s后返回
3.1 使用 DeferredResult
@GetMapping("/waitMethod1")
public DeferredResult<String> waitMethod1(String id) {
DeferredResult<String> deferredResult = new DeferredResult<>(30_000L, "timeout");
// 设置超时回调
deferredResult.onTimeout(() -> {
waitingRequests1Map.remove(id);
log.info("DeferredResult {} 超时结束", id);
});
// 设置完成回调
deferredResult.onCompletion(() -> {
waitingRequests1Map.remove(id);
log.info("DeferredResult {} 正常结束", id);
});
waitingRequests1Map.put(id, deferredResult);
return deferredResult;
}
@GetMapping("/endWaitMethod1")
public String endWaitMethod1(String id) {
DeferredResult<String> deferredResult = waitingRequests1Map.get(id);
if (deferredResult != null && !deferredResult.hasResult()) {
deferredResult.setResult("cancel");
}
return "end";
}
3.2 使用 CompletableFuture
@GetMapping("/waitMethod2")
public CompletableFuture<String> waitMethod2(String id) {
CompletableFuture<String> waitingFuture = new CompletableFuture<>();
CompletableFuture<String> timeoutFuture = CompletableFuture
.supplyAsync(() -> "超时返回",
CompletableFuture.delayedExecutor(30, TimeUnit.SECONDS));
waitingRequests2Map.put(id, waitingFuture);
return waitingFuture.applyToEither(timeoutFuture, Function.identity())
.whenComplete((result, throwable) -> {
waitingRequests2Map.remove(id);
if (!waitingFuture.isDone()) waitingFuture.cancel(false);
if (!timeoutFuture.isDone()) timeoutFuture.cancel(false);
});
}
@GetMapping("/endWaitMethod2")
public String endWaitMethod2(String id) {
CompletableFuture<String> future = waitingRequests2Map.get(id);
if (future != null && !future.isDone()) {
future.complete("cancel");
}
return "end";
}
更多推荐


所有评论(0)