异步响应
为什么需要异步处理?
Section titled “为什么需要异步处理?”在处理 HTTP 请求时,有时需要执行耗时操作,如数据库查询、远程 API 调用或复杂计算。这些操作如果在主线程中同步执行,会阻塞服务器处理其他请求,降低系统的吞吐量。
Feat 框架提供了简单高效的异步处理机制,让你能够轻松实现非阻塞的 HTTP 请求处理。
异步处理原理
Section titled “异步处理原理”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。覆盖这个默认实现,即可实现真正的异步处理。
实现异步处理
Section titled “实现异步处理”- 覆盖
handle(HttpRequest request, CompletableFuture<Void> future)方法 - 在单独的线程中执行耗时操作
- 操作完成后调用
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 秒后返回,同时服务器可以继续处理其他请求。
异步处理的优势
Section titled “异步处理的优势”| 优势 | 说明 |
|---|---|
| 提高吞吐量 | 主线程不会被阻塞,可继续处理其他请求 |
| 更好的资源利用 | 可根据系统资源调整线程池大小 |
| 更好的用户体验 | 服务器可处理更多并发请求 |
| 灵活的异常处理 | 可通过 future.completeExceptionally(throwable) 传递异常 |
1. 合理设置线程池大小
Section titled “1. 合理设置线程池大小”// 根据 CPU 核心数设置int poolSize = Runtime.getRuntime().availableProcessors();ExecutorService executorService = Executors.newFixedThreadPool(poolSize);
// I/O 密集型任务可适当增加ExecutorService ioIntensivePool = Executors.newFixedThreadPool(poolSize * 2);2. 正确处理异常
Section titled “2. 正确处理异常”executorService.execute(() -> { try { // 业务逻辑 doSomething(request); future.complete(null); } catch (Exception e) { // 记录错误并完成 future System.err.println("处理失败: " + e.getMessage()); future.completeExceptionally(e); }});3. 及时释放资源
Section titled “3. 及时释放资源”// 应用关闭时关闭线程池Runtime.getRuntime().addShutdownHook(new Thread(() -> { executorService.shutdown();}));- 了解 Router 路由组件 构建更复杂的路由
- 学习 HTTPS 配置 保护你的服务
- 探索 Feat Cloud 获得更高级的编程体验