Skip to content

异步响应

This content is not available in your language yet.

在处理 HTTP 请求时,有时需要执行耗时操作,如数据库查询、远程 API 调用或复杂计算。这些操作如果在主线程中同步执行,会阻塞服务器处理其他请求,降低系统的吞吐量。

Feat 框架提供了简单高效的异步处理机制,让你能够轻松实现非阻塞的 HTTP 请求处理。

Feat 框架的异步处理基于 Java 的 CompletableFuture,允许将请求处理逻辑放在独立的线程中执行,而不会阻塞 HTTP 服务器的主线程。

HttpHandler 接口提供了两个 handle 方法:

// 同步处理方法
void handle(HttpRequest request) throws Throwable;
// 异步处理方法
default void handle(HttpRequest request, CompletableFuture<Void> future) throws Throwable {
try {
handle(request);
} finally {
future.complete(null);
}
}

默认情况下,异步方法会调用同步方法,并在处理完成后自动完成 CompletableFuture。覆盖这个默认实现,即可实现真正的异步处理。

  1. 覆盖 handle(HttpRequest request, CompletableFuture<Void> future) 方法
  2. 在单独的线程中执行耗时操作
  3. 操作完成后调用 future.complete(null)
import tech.smartboot.feat.core.server.HttpHandler;
import tech.smartboot.feat.core.server.HttpRequest;
import tech.smartboot.feat.core.server.HttpServer;
import java.util.Date;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class AsyncHttpDemo {
public static void main(String[] args) {
// 1. 创建线程池用于执行异步任务
ExecutorService executorService = Executors.newFixedThreadPool(
Runtime.getRuntime().availableProcessors()
);
// 2. 创建 HTTP 服务器
HttpServer bootstrap = new HttpServer();
// 3. 设置异步处理器
bootstrap.httpHandler(new HttpHandler() {
@Override
public void handle(HttpRequest request, CompletableFuture<Void> future) {
// 4. 将耗时操作提交到线程池执行
executorService.execute(() -> {
try {
// 5. 模拟耗时操作(如数据库查询)
Thread.sleep(1000);
// 6. 写入响应
String content = new Date() + " currentThread:" + Thread.currentThread();
request.getResponse().write(content.getBytes());
} catch (Exception e) {
// 7. 异常处理:输出错误信息
System.err.println("异步处理失败: " + e.getMessage());
} finally {
// 8. 完成异步处理(必须调用)
future.complete(null);
}
});
}
@Override
public void handle(HttpRequest request) throws Throwable {
// 异步模式下此方法不会被调用
}
});
// 9. 启动服务器
bootstrap.listen(8080);
System.out.println("服务已启动: http://localhost:8080");
}
}

运行上述代码后,访问 http://localhost:8080 ,你应该看到类似以下输出:

Fri Jan 15 10:30:00 CST 2025 currentThread:Thread[pool-1-thread-1,5,main]

每次刷新页面,响应会在约 1 秒后返回,同时服务器可以继续处理其他请求。

优势说明
提高吞吐量主线程不会被阻塞,可继续处理其他请求
更好的资源利用可根据系统资源调整线程池大小
更好的用户体验服务器可处理更多并发请求
灵活的异常处理可通过 future.completeExceptionally(throwable) 传递异常
// 根据 CPU 核心数设置
int poolSize = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
// I/O 密集型任务可适当增加
ExecutorService ioIntensivePool = Executors.newFixedThreadPool(poolSize * 2);
executorService.execute(() -> {
try {
// 业务逻辑
doSomething(request);
future.complete(null);
} catch (Exception e) {
// 记录错误并完成 future
System.err.println("处理失败: " + e.getMessage());
future.completeExceptionally(e);
}
});
// 应用关闭时关闭线程池
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
executorService.shutdown();
}));