SpringBoot 项目启动十几秒,我一般不会觉得有什么问题。
但如果这是个 Serverless 函数,或者 K8s 正在扩容,十几秒就有点扎眼了。实例还没起来,请求已经压过来了。
Quarkus 就是盯着这个地方下手的。
网上流传很广的一个数字是:0.0015 秒启动一个应用。
这个数字确实够吓人,不过这里先把坑堵上:别把 0.0015 秒理解成所有 Quarkus 项目都能稳定做到 1.5ms 启动。它通常指 Native 场景下的极限案例,不同依赖、机器、业务代码差距会非常大。Quarkus 官方现在强调的也是 Native Image 的快速启动和低内存,而不是保证一个固定的 1.5ms。官方自己的历史示例里,Native 应用有过 0.023s 左右的启动记录。
但即使不盯着 1.5ms,这东西的启动速度还是很有意思。
我第一眼看 Quarkus,最想知道的不是它注解怎么写,而是:
凭什么比我们用了这么多年的 SpringBoot 启动快?
SpringBoot 启动时干了不少活。
扫描 Class、创建 Bean、解析配置、处理各种自动配置,再把 Web 容器拉起来。项目小的时候没感觉,依赖一多,启动日志刷半天很正常。
Quarkus 的路子有点不一样。
它尽量把运行时要干的事情,提前挪到了构建阶段。
能提前分析的 Bean,提前分析;能提前确定的依赖关系,提前确定;一些初始化工作也往构建阶段搬。Quarkus 官方 Native Reference 里专门提到了 Build-time Initialization,这也是它启动快的关键之一。
这招挺狠。
以前是:
启动应用
加载 Class
分析依赖
初始化框架
创建对象
提供服务
Quarkus 更像:
构建时先算一大半
生成最终应用
启动时少干活
直接提供服务
尤其再配上 GraalVM Native Image,JVM 启动这层成本还能继续往下压。
我随手写个订单价格预览接口,代码并没有想象中那么怪:
@Path("/price")
@Produces(MediaType.APPLICATION_JSON)
public class PriceResource {
@Inject
PriceCalculator calculator;
@GET
@Path("/{sku}")
public PriceView query(@PathParam("sku") String sku) {
return calculator.calculate(sku);
}
}
业务类也很普通:
@ApplicationScoped
public class PriceCalculator {
public PriceView calculate(String sku) {
BigDecimal origin = loadPrice(sku);
BigDecimal payable = origin.compareTo(new BigDecimal("100")) >= 0
? origin.subtract(new BigDecimal("8"))
: origin;
return new PriceView(sku, origin, payable);
}
private BigDecimal loadPrice(String sku) {
// 实际项目这里通常查缓存或数据库
return new BigDecimal("128.00");
}
}
如果之前一直写 SpringBoot,这套东西基本不用重新学 Java。
@RestController换成 JAX-RS 的@Path,依赖注入还是依赖注入,配置、数据库、Redis、Kafka 这些常用东西也都有对应扩展。
真正让我觉得 Quarkus 有点东西的,是 Native。
普通方式照样可以:
./mvnw package
java -jar target/quarkus-app/quarkus-run.jar
如果环境准备好了,可以直接构建 Native:
./mvnw install -Dnative
最后出来的不再只是一个等 JVM 拉起的传统 Jar,而是 Native Executable。Quarkus 官方文档也明确说明,Native Executable 会包含应用代码、需要的库、Java API 以及精简后的 VM,从而改善启动速度和运行时占用。
这时候它的价值就出来了。
比如一个服务平时只有 3 个实例,流量突然上来需要扩到 20 个。
传统 Java 服务:
Pod 创建
JVM 启动
Spring Context 初始化
Bean 创建
健康检查通过
开始接流量
扩容不是点一下数字就完事,新实例什么时候真正 Ready 才重要。
Serverless 更明显。
一次请求来了,平台临时拉实例。如果应用自己启动就得好几秒,用户其实是在替 JVM 冷启动买单。
所以我不会因为 Quarkus 跑得快,就把公司几十个 SpringBoot 服务全部重写一遍。
这种操作纯属给自己找事故。
老系统已经跑稳了,SpringBoot 生态成熟,组件也全,没必要为了一个启动数字折腾。
但下面这些新项目,我会认真考虑 Quarkus:
云原生微服务、Serverless、短生命周期任务、需要快速弹性扩缩容的服务,以及对容器内存比较敏感的应用。
还有一点得提前说。
Native 不是白送的。
Quarkus 把很多运行时工作搬到了构建阶段,代价就是Native 构建通常更重。官方在 2026 年的一篇文章里也直接提到,相比 SpringBoot,Quarkus 在启动时间和内存方面表现很好,但构建时间会更高,因为更多工作被提前到了 Build Time。
另外,反射、动态类加载、某些第三方库到了 GraalVM Native Image 下也可能需要额外处理。官方甚至单独整理了一份 Native Application Tips 来处理资源、反射等兼容问题。
所以“换掉 SpringBoot”这句话,我更愿意加个条件。
不是 SpringBoot 不行了。
而是以前 Java 服务长期运行,启动 10 秒、20 秒,大家没那么在意。现在容器、K8s、Serverless 把实例生命周期越切越短,启动速度和内存占用突然变成了架构指标。
这时候再看 Quarkus,就知道它为什么敢把自己叫:
Supersonic Subatomic Java。
如果下一套系统本来就是奔着云原生去的,我大概率不会条件反射地先建一个 SpringBoot 项目。
Quarkus,至少值得先跑一遍。