今天来看一下 Quarkus 构建出来的本机可执行文件到底比 Spring 应用能快多少, 生态的成熟度不在这里讨论 。
TLDR
先上结论, 与只有一个 Controller 的Spring Web 应用做下对比。
应用启动时间:0.012s vs 2.294s
镜像大小:49MB vs 237 MB
Spring 应用镜像使用 openjdk:11.0-jre-slim 作为 base 镜像,大小为 220MB。
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
spring/spring-getting-started latest 5f47030c5c3f 6 minutes ago 237MB
quarkus/quarkus-getting-started distroless2 fe973c5ac172 24 minutes ago 49MB
quarkus/quarkus-getting-started distroless 6fe27dd44e86 31 minutes ago 51MB
quarkus/quarkus-getting-started ubi 8f86f5915715 58 minutes ago 132MB
Java 应用容器化的困境
云原生世界中,应用容器化是个显著的特点。Java 应用容器化时面临了如下问题:
- 应用启动慢:其实这是 Java 应用的问题。Java 应用占用内存多;JVM 虚拟机启动时需要做环境的初始化、预加载大量的类、初始化线程等等。启动耗时视应用情况需要几秒,甚至可达分钟级。较长的启动耗时,也抑制了水平伸缩性。即使在 Serverless 这种响应耗时要求不高的场景,也会被嫌弃。
- 镜像过大:其实使用了镜像的分层设计,常见的一个 SpringCloud 应用的 über-jar 包可能都有 7、80MB。
- 空间占用:虽然用了镜像分层,但积少成多,也会增加存储成本。
Quarkus 与本机映像(native image)
Quarkus 的开发遵从了容器优先的原则:
- 支持 Graal/SubstrateVM
- 构建时处理元数据
- 减少反射的使用
- 本机映像预启动
本机映像是将 Java 代码提前编译为可执行文件(称为本机映像)的技术。该可执行文件包括应用程序类、其依赖项中的类、运行时间类以及 JDK 中的静态链接本机代码。它不是在 Java VM 上运行,而是包括必要的组件,例如内存管理,线程调度等,这些组件来自另一个运行时系统 “Substrate VM”。“Substrate VM” 是运行时组件(例如反优化器,垃圾收集器,线程调度等)的名称。与 JVM 相比,生成的程序具有更快的启动时间和更低的运行时内存开销。
如何构建本机映像
环境配置参考 上一篇文章 ,可以直接 从这里下载源码 。
配置 GraalVM
之前我们使用了 sdkman 进行 GraalVM 安装。设置 GRAALVM_HOME 环境变量:
export GRAALVM_HOME=`sdk home java 21.0.0.2.r11-grl`
使用 gu 安装 native-image :
${GRAALVM_HOME}/bin/gu install native-image
构建本机可执行文件
在源码