1. 概述
本文将聚焦两个知名 Java 框架——Spring Boot 和 Quarkus 的简单对比。通过分析,我们将更清晰地理解它们的异同点及特性。同时,我们还会进行性能测试,观察两者的实际表现。
2. Spring Boot
Spring Boot 是一个面向企业级应用的 Java 框架。它整合了所有 Spring 项目,通过提供大量生产就绪的集成方案来提升开发效率。
这种方式显著减少了配置和样板代码。此外,得益于其"约定优于配置"的理念(根据运行时类路径中的依赖自动注册默认配置),Spring Boot 大幅缩短了 Java 应用的上市时间。
3. Quarkus
Quarkus 是另一个与 Spring Boot 理念相似的框架,但额外承诺提供更小的构建产物、更快的启动时间以及更优的资源利用效率。
它专为云原生、无服务器和容器化环境优化。尽管侧重点略有不同,Quarkus 同样能良好集成主流 Java 框架。
4. 对比分析
如前所述,两个框架都能良好集成其他项目。但它们的内部实现和架构存在差异:例如 Spring Boot 提供两种 Web 实现方式:阻塞式(Servlets) 和 非阻塞式(WebFlux)。
Quarkus 也支持两种模式,但与 Spring Boot 不同,它允许同时使用阻塞和非阻塞策略。此外,Quarkus 将响应式编程深度嵌入其架构。
因此,我们将使用 Spring WebFlux 和 Quarkus 响应式能力构建的全响应式应用进行对比,以确保测试场景更精确。
另一个重要特性是两者都支持创建原生镜像(二进制可执行文件)。因此,我们也将原生镜像纳入对比范围。
注意:本文使用 Spring Boot 3.1.3。虽然旧版可通过配置支持原生镜像(原生支持曾处于实验阶段),但从 3.x 版本开始已正式支持,需配合 GraalVM 使用。
4.1 测试应用
我们的应用暴露三个接口:
- 创建邮编
- 查询特定邮编信息
- 按城市查询邮编
这些接口使用 Spring Boot 和 Quarkus 以全响应式方式实现,并连接 MySQL 数据库。目标是构建一个比 Hello World 稍复杂的示例应用。当然,数据库驱动和序列化框架等实现会影响对比结果,但大多数应用都会涉及这些组件。
因此,本对比并非要判定哪个框架绝对更优,而是针对特定实现的案例分析。
4.2 测试方案
使用 Wrk 执行测试,通过其指标报告分析结果。同时用 VisualVM 监控测试期间的应用资源消耗。
测试持续 5 分钟,包含预热阶段,连接数逐步增至 20。Wrk 配置如下:
尽管因缺乏进程隔离不够理想,但测试仅用于说明对比方案,并非提供详尽的性能分析。
提示:根据机器配置,可能需要调整连接数、线程数等参数。
4.3 测试要点
确保测试对象准确至关重要。我们使用 Docker 部署基础设施,以控制应用和数据库的资源约束。目标是压测应用而非底层系统或数据库。本例中限制 CPU 数量即可,具体值需根据机器资源调整。
资源限制可通过 Docker 设置、cpulimit
命令或其他工具实现。使用 docker stats
和 top
监控系统资源。内存方面,我们测量堆内存使用量和 RSS,通过 ps -o pid,rss,command -p <pid>
命令获取。
5. 测试发现
两个框架的开发体验都不错,但需注意:
- Spring Boot 文档更完善,网上资源更丰富
- Quarkus 正在快速改进,提供大量提升效率的特性,但在文档和 Stack Overflow 支持上仍有差距
关键指标对比:
指标 | Spring Boot JVM | Quarkus JVM | Spring Boot Native | Quarkus Native |
---|---|---|---|---|
启动时间 (秒) | 5.395 | 4.075 | 0.082 | 0.142 |
构建时间 (秒) | 1.759 | 5.243 | 113 | 91 |
构建产物大小 (MB) | 30.0 | 31.8 | 94.7 | 80.5 |
加载类数量 | 8861 | 8496 | 21615 | 16040 |
CPU 峰值使用率 (%) | 100 | 100 | 100 | 100 |
CPU 平均使用率 (%) | 82 | 73 | 94 | 92 |
启动堆大小 (MB) | 1048.57 | 1056.96 | – | – |
启动堆使用量 (MB) | 193.31 | 157.066 | 84.574 | 60.41 |
堆峰值使用量 (MB) | 604.1 | 567.854 | 144.984 | 519.526 |
堆平均使用量 (MB) | 434.155 | 362.46 | 114.779 | 289.968 |
启动 RSS 内存 (MB) | 197.7 | 159.1 | 90.5 | 57.1 |
最大线程数 | 77 | 47 | 73 | 42 |
每秒请求数 | 61403.5 | 57009.5 | 78762.5 | 50565.83 |
关键发现:
- 启动时间:Quarkus 在 JVM 和原生版本均快于 Spring Boot
- 构建时间:原生镜像构建 Quarkus (91秒) 优于 Spring Boot (113秒),但 JVM 构建相反(Spring Boot 1.75秒 vs Quarkus 5.24秒)
- 产物大小:JVM 版本相近,原生镜像 Quarkus (80.5MB) 优于 Spring Boot (94.7MB)
其他指标分析如下:
5.1 CPU 表现
JVM 版本在预热阶段 CPU 消耗更高,之后趋于稳定。各版本消耗差异微小:
Quarkus 略占优势,但差异极小可视为平局。测试中我们将应用 CPU 限制为 3 核,确保压测对象而非系统资源。
5.2 内存表现
内存分析更复杂:
- JVM 版本:堆预留量相近,但 Quarkus 堆使用量略低(差异极小)
- 原生镜像:Spring Native 垃圾回收更频繁,内存占用更低
另一个重要发现:Quarkus 在 RSS 内存指标上全面领先(仅展示启动数据,测试中可持续监控)。
注意:测试使用默认参数,未调整 GC 或 JVM 选项。实际生产环境需根据应用特性定制配置。
5.4 综合分析
整体来看,两个框架都是实现 Java 应用的优秀选择:
- 原生镜像:启动快、资源消耗低,适合无服务器、短生命周期应用及资源敏感场景
- JVM 应用:运行时开销较高,但长期稳定性和吞吐量出色,适合健壮的长生命周期应用
最终结论:所有版本性能表现强劲(至少在我们的示例中),差异微小可视为性能相当。虽然 JVM 版本吞吐量更高但消耗更多资源,而原生版本更省资源,但这些差异在具体场景中可能并不显著。
踩坑提醒:测试中 Spring 应用因驱动问题被迫切换数据库驱动,而 Quarkus 开箱即用无此问题。
6. 总结
本文对比了 Spring Boot 和 Quarkus 框架及其 JVM/原生部署模式,并分析了多项指标。测试应用代码及脚本可在 GitHub 获取。