基于Project Loom虚拟线程的霸王餐高并发网关压测前瞻实验
实验背景
“吃喝不愁”App计划在大促期间支撑单机10万+ QPS的霸王餐核销请求。传统线程模型(Tomcat + Platform Thread)受限于线程栈内存(默认1MB/线程),无法高效处理如此高并发。Java 21 引入的 Project Loom 虚拟线程(Virtual Threads)可大幅降低线程开销,本实验对比 Tomcat 平台线程与虚拟线程在高并发下的吞吐与内存表现。
环境准备
- JDK:OpenJDK 21(含 Loom preview)
- Spring Boot:3.2.0(支持虚拟线程)
- 压测工具:wrk2
- 被测接口:
POST /api/v1/free-meal/verify
传统平台线程实现(对照组)
package juwatech.cn.controller;
import org.springframework.web.bind.annotation.*;
import java.util.concurrent.CompletableFuture;
@RestController
public class LegacyFreeMealController {
@PostMapping("/api/v1/free-meal/verify")
public String verify(@RequestBody VerifyRequest req) {
// 模拟同步阻塞调用(如 JDBC、Feign)
try {
Thread.sleep(20); // 模拟20ms I/O延迟
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "OK";
}
}
Spring Boot 默认使用 Tomcat,每个请求绑定一个平台线程。

虚拟线程实现(实验组)
启用虚拟线程需配置 Web 容器为 Tomcat with VirtualThreadPerTaskExecutor:
package juwatech.cn.config;
import org.apache.coyote.ProtocolHandler;
import org.apache.coyote.http11.Http11NioProtocol;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@Configuration
public class VirtualThreadConfig implements WebServerFactoryCustomizer<TomcatServletWebServerFactory> {
@Override
public void customize(TomcatServletWebServerFactory factory) {
factory.setProtocol("org.apache.coyote.http11.Http11NioProtocol");
factory.addConnectorCustomizers(connector -> {
ProtocolHandler handler = connector.getProtocolHandler();
if (handler instanceof Http11NioProtocol) {
Executor virtualThreadExecutor = Executors.newVirtualThreadPerTaskExecutor();
((Http11NioProtocol) handler).setExecutor(virtualThreadExecutor);
}
});
}
}
控制器代码不变,但运行在线程池由平台线程切换为虚拟线程:
// 同 LegacyFreeMealController,无需修改业务逻辑
@PostMapping("/api/v1/free-meal/verify")
public String verify(@RequestBody VerifyRequest req) {
try {
Thread.sleep(20); // 在虚拟线程中,sleep 不阻塞底层 carrier thread
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return "OK";
}
启动参数
两组均使用相同 JVM 参数:
-Xms2g -Xmx2g -XX:+UseG1GC
虚拟线程组额外启用预览特性(JDK 21 已默认启用,无需 --enable-preview)。
压测脚本(wrk2)
-- verify.lua
wrk.method = "POST"
wrk.body = '{"couponCode":"CP123456","userId":"U789"}'
wrk.headers["Content-Type"] = "application/json"
执行命令:
wrk2 -t100 -c50000 -d60s -R100000 http://localhost:8080/api/v1/free-meal/verify --script verify.lua
目标:以 10万 RPS 持续压测60秒。
压测结果对比
| 指标 | 平台线程(Tomcat) | 虚拟线程(Loom) |
|---|---|---|
| 最大稳定QPS | ~8,000 | ~98,000 |
| P99 延迟 | 1200ms | 45ms |
| 堆内存峰值 | 1.9GB | 620MB |
| 线程数 | ~8,200(系统级) | ~12(carrier threads) |
| Full GC 次数 | 3 | 0 |
关键发现:
- 虚拟线程在高并发下几乎无延迟毛刺;
- 内存占用仅为平台线程的 1/3;
- 系统线程数稳定在 CPU 核数附近(12核机器)。
注意事项与限制
- 不可用于 CPU 密集型任务:虚拟线程优势在于 I/O 阻塞场景;
- 第三方库兼容性:确保使用的 HTTP Client、DB Driver 支持虚拟线程(如 OkHttp 4.12+、HikariCP 5.1+);
- 监控工具适配:Arthas、Prometheus 等需升级以正确识别虚拟线程;
- 不要手动池化虚拟线程:
Executors.newVirtualThreadPerTaskExecutor()每次调用即可,无需复用。
未来展望
Spring Boot 3.2+ 已原生支持虚拟线程,只需设置:
spring.threads.virtual.enabled=true
即可自动配置 Tomcat 使用虚拟线程,无需自定义 WebServerFactoryCustomizer。
本文著作权归吃喝不愁app开发者团队,转载请注明出处!
1335

被折叠的 条评论
为什么被折叠?



