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 statstop 监控系统资源。内存方面,我们测量堆内存使用量和 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 消耗更高,之后趋于稳定。各版本消耗差异微小:

(Spring JVM) Spring CPU

(Quarkus JVM) Quarkus CPU

(Spring Native) Spring Native CPU

(Quarkus Native) Quarkus Native CPU

Quarkus 略占优势,但差异极小可视为平局。测试中我们将应用 CPU 限制为 3 核,确保压测对象而非系统资源。

5.2 内存表现

内存分析更复杂:

  • JVM 版本:堆预留量相近,但 Quarkus 堆使用量略低(差异极小)

(Spring Boot JVM) Spring 内存

(Quarkus JVM) Quarkus 内存

  • 原生镜像Spring Native 垃圾回收更频繁,内存占用更低

(Spring Boot Native) Spring Native 内存

(Quarkus Native) Quarkus Native 内存

另一个重要发现:Quarkus 在 RSS 内存指标上全面领先(仅展示启动数据,测试中可持续监控)。

注意:测试使用默认参数,未调整 GC 或 JVM 选项。实际生产环境需根据应用特性定制配置。

5.4 综合分析

整体来看,两个框架都是实现 Java 应用的优秀选择:

  • 原生镜像:启动快、资源消耗低,适合无服务器、短生命周期应用及资源敏感场景
  • JVM 应用:运行时开销较高,但长期稳定性和吞吐量出色,适合健壮的长生命周期应用

最终结论:所有版本性能表现强劲(至少在我们的示例中),差异微小可视为性能相当。虽然 JVM 版本吞吐量更高但消耗更多资源,而原生版本更省资源,但这些差异在具体场景中可能并不显著。

踩坑提醒:测试中 Spring 应用因驱动问题被迫切换数据库驱动,而 Quarkus 开箱即用无此问题。

6. 总结

本文对比了 Spring Boot 和 Quarkus 框架及其 JVM/原生部署模式,并分析了多项指标。测试应用代码及脚本可在 GitHub 获取。


原始标题:Spring Boot vs Quarkus