异步处理
当请求处理涉及数据库查询、远程 HTTP 调用、文件 IO 等耗时操作时,应该使用异步处理模式。这样可以将工作移出 Feat 的主处理线程,避免阻塞其他请求,显著提升并发处理能力。
同步 vs 异步
Section titled “同步 vs 异步”| 特性 | 同步处理 | 异步处理 |
|---|---|---|
| 执行线程 | 主处理线程 | 自定义线程池 |
| 阻塞影响 | 阻塞主线程,降低并发 | 不阻塞主线程 |
| 适用场景 | 简单、快速的操作 | 耗时操作(>10ms) |
| 代码复杂度 | 简单 | 需要管理 CompletableFuture |
异步处理模型
Section titled “异步处理模型”Feat 的异步处理依赖 HttpHandler 接口的双参数方法:
void handle(HttpRequest request, CompletableFuture<Void> future)使用异步模式只需做两件事:
- 将耗时逻辑放到自定义线程池执行
- 完成后调用
future.complete(null)通知 Feat
创建异步处理器
Section titled “创建异步处理器”import tech.smartboot.feat.Feat;import tech.smartboot.feat.core.server.HttpHandler;import tech.smartboot.feat.core.server.HttpRequest;
import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class AsyncDemo { public static void main(String[] args) { // 创建业务线程池 ExecutorService executor = Executors.newFixedThreadPool(4);
Feat.httpServer() .httpHandler(new HttpHandler() { @Override public void handle(HttpRequest request, CompletableFuture<Void> future) { executor.execute(() -> { try { // 模拟耗时操作 Thread.sleep(100); request.getResponse().write("Async response"); } catch (Exception e) { e.printStackTrace(); } finally { // 必须调用,否则请求不会结束 future.complete(null); } }); }
@Override public void handle(HttpRequest request) { // 异步模式下这里不处理主逻辑 } }) .listen(8080); }}使用 Lambda 简化
Section titled “使用 Lambda 简化”如果不需要复杂的线程池管理,可以用 Lambda 快速创建异步处理器:
Feat.httpServer() .httpHandler(new HttpHandler() { @Override public void handle(HttpRequest request, CompletableFuture<Void> future) { CompletableFuture.supplyAsync(() -> { // 耗时操作 return fetchDataFromDatabase(); }).thenAccept(result -> { request.getResponse().write(result); future.complete(null); // 完成后通知 Feat }); }
@Override public void handle(HttpRequest request) { } }) .listen(8080);回调触发流程
Section titled “回调触发流程”以下泳道图展示了异步请求的处理流程:
sequenceDiagram
autonumber
participant Client as 客户端
participant Feat as Feat 服务器
participant ThreadPool as 业务线程池
participant Handler as HttpHandler
Client->>Feat: HTTP Request
Feat->>Handler: handle(request, future)
Handler->>ThreadPool: 提交耗时任务
Handler-->>Feat: 立即返回(不阻塞)
Feat->>Feat: 继续处理其他请求
ThreadPool->>ThreadPool: 执行耗时操作
ThreadPool->>Feat: 写入响应
ThreadPool->>Handler: future.complete(null)
Handler-->>Feat: 通知请求完成
Feat-->>Client: HTTP Response
流程说明:
- 接收请求 - Feat 主线程接收 HTTP 请求
- 调用处理器 - 调用
handle(request, future)方法 - 提交任务 - 将耗时操作提交到业务线程池
- 立即返回 - 主线程立即返回,继续处理其他请求
- 异步执行 - 业务线程池执行耗时操作
- 完成通知 - 调用
future.complete(null)通知 Feat 请求完成 - 发送响应 - Feat 将响应发送给客户端
数据库查询场景
Section titled “数据库查询场景”import tech.smartboot.feat.Feat;import tech.smartboot.feat.core.server.HttpHandler;import tech.smartboot.feat.core.server.HttpRequest;
import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class AsyncDatabaseDemo { // 业务线程池 private static final ExecutorService executor = Executors.newFixedThreadPool(8);
public static void main(String[] args) { Feat.httpServer(options -> options.debug(true)) .httpHandler(new HttpHandler() { @Override public void handle(HttpRequest request, CompletableFuture<Void> future) { String userId = request.getParameter("id");
executor.execute(() -> { try { // 模拟数据库查询 User user = queryDatabase(userId);
if (user != null) { request.getResponse().write( "{\"id\":\"" + user.id + "\",\"name\":\"" + user.name + "\"}" ); } else { request.getResponse().setHttpStatus(404); request.getResponse().write("User not found"); } } catch (Exception e) { request.getResponse().setHttpStatus(500); request.getResponse().write("Internal error"); e.printStackTrace(); } finally { // 无论成功失败,都要完成 future future.complete(null); } }); }
@Override public void handle(HttpRequest request) { } }) .listen(8080); }
static User queryDatabase(String userId) throws InterruptedException { // 模拟数据库查询耗时 Thread.sleep(50); return new User(userId, "User_" + userId); }
static class User { String id, name; User(String id, String name) { this.id = id; this.name = name; } }}外部 API 调用场景
Section titled “外部 API 调用场景”import tech.smartboot.feat.Feat;import tech.smartboot.feat.core.server.HttpHandler;import tech.smartboot.feat.core.server.HttpRequest;
import java.util.concurrent.CompletableFuture;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;
public class AsyncHttpCallDemo { private static final ExecutorService executor = Executors.newFixedThreadPool(4);
public static void main(String[] args) { Feat.httpServer() .httpHandler(new HttpHandler() { @Override public void handle(HttpRequest request, CompletableFuture<Void> future) { executor.execute(() -> { try { // 调用外部 API String result = callExternalApi(); request.getResponse().write(result); } catch (Exception e) { request.getResponse().setHttpStatus(502); request.getResponse().write("External service error"); } finally { future.complete(null); } }); }
@Override public void handle(HttpRequest request) { } }) .listen(8080); }
static String callExternalApi() throws InterruptedException { // 模拟 HTTP 调用耗时 Thread.sleep(200); return "{\"status\":\"ok\",\"data\":[]}"; }}