当微服务跑在 Kubernetes 上,Java 传统的”启动慢、吃内存”就成了硬伤。Quarkus 是红帽推出的”超音速亚原子”Java 框架,主打容器优先与 GraalVM 原生镜像,把启动压到毫秒级、内存砍掉大半,是云原生 Java 微服务的一条新路线。本文用可落地的代码,带你从零跑通 Quarkus 的原生镜像构建与 K8s 部署。
一、Quarkus 为什么适合云原生
传统 Java 应用是”运行期才做大量决策”:类扫描、反射、代理在启动时反复发生,导致 Spring Boot 应用冷启动动辄数秒、常驻内存上百 MB。Quarkus 反其道而行,把能提前算清楚的都放到构建期完成(build-time augmentation),运行期只保留最小闭环。再叠加 GraalVM 的 原生镜像(native image),直接编译成不依赖 JVM 的可执行文件,启动几乎瞬时、内存占用大幅下降。
它与你熟悉的 Spring Boot 3 并非二选一:Quarkus 同样支持 REST、依赖注入、配置、事务等常规能力,只是底层默认走响应式(RESTEasy Reactive)与编译期优化。下面对比一下两者在云原生场景下的差异:
| 维度 | Quarkus(原生) | Spring Boot(JVM) |
|---|---|---|
| 冷启动 | 毫秒级 | 1–5 秒 |
| 常驻内存 | 约 1/3–1/5 | 100MB+ |
| 构建产物 | 可执行文件 / 轻量镜像 | Fat Jar |
| 响应式默认 | 是(Reactive) | 可选(WebMvc) |
| 生态成熟度 | 成长中 | 非常成熟 |
二、快速起步:用脚手架生成项目
最简单的方式是访问 code.quarkus.io 勾选扩展,或用 Quarkus CLI / Maven 直接生成。下面用 Maven 插件生成一个带 REST 与容器镜像支持的工程:
mvn io.quarkus.platform:quarkus-maven-plugin:3.13.0:create \
-DprojectGroupId=com.demo \
-DprojectArtifactId=quarkus-demo \
-Dextensions="resteasy-reactive,container-image-docker,quarkus-kubernetes"
cd quarkus-demo
./mvnw quarkus:dev # 热重载开发模式,改代码即时生效
三、第一个 REST 接口
Quarkus 的 RESTEasy Reactive 用 Jakarta REST 注解,写法与 JAX-RS 一致,但底层是非阻塞的。下面写一个简单的健康检查与业务接口:
package com.demo;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
@Path("/hello")
public class HelloResource {
@GET
@Produces(MediaType.TEXT_PLAIN)
public String hello() {
return "Hello from Quarkus!";
}
}
启动 quarkus:dev 后访问 http://localhost:8080/hello 即可看到返回。注意 Quarkus 默认端口是 8080,配置都集中在 src/main/resources/application.properties。
四、构建 GraalVM 原生镜像
原生镜像需要本地安装 GraalVM 并启用 native-image 工具。构建命令如下:
# 安装 GraalVM(以 SDKMAN 为例)
sdk install java 21.3.3.r17-grl
sdk use java 21.3.3.r17-grl
gu install native-image
# 执行原生编译(会预演运行期行为,耗时较长)
./mvnw package -Dnative
# 产物:./target/quarkus-demo-1.0.0-SNAPSHOT-runner
编译出的 runner 是可执行文件,直接 ./target/*-runner 启动,毫秒级拉起。若你看过 Spring Boot 的 GraalVM 原生镜像编译,会发现 Quarkus 对原生支持是一等公民,扩展会自动处理反射注册,踩坑更少。
五、配置与外部化
Quarkus 的配置体系与 Spring 类似,但更强调”编译期可冻结”。多环境用 %prod、%dev 前缀区分:
# application.properties
quarkus.http.port=8080
greeting.name=Quarkus
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://db:5432/demo
%prod.quarkus.datasource.username=app
%prod.quarkus.datasource.password=${DB_PASSWORD:changeit}
六、结合 Java 21 虚拟线程
Quarkus 与 Java 21 虚拟线程 是天作之合:用 @RunOnVirtualThread 标注的接口,每个请求跑在一个轻量虚拟线程上,既保留了命令式代码的书写手感,又获得接近响应式的吞吐。特别适合有大量阻塞 I/O(数据库、HTTP 调用)的场景。
@Path("/orders")
public class OrderResource {
@GET
@RunOnVirtualThread
public List<Order> list() {
// 看似阻塞调用,实则运行在虚拟线程上,不占平台线程
return orderRepository.findAll();
}
}
七、打包容器镜像并部署到 K8s
Quarkus 的”容器优先”不是口号:借助 container-image-docker 扩展,一条命令就能产出精简镜像;配合 quarkus-kubernetes 还能自动生成 Deployment/Service 清单。关于镜像构建与 Docker 基础 的更多实践可回顾本站相关文章。
# 构建原生可执行文件后再打成 distroless 镜像
./mvnw package -Dnative -Dquarkus.container-image.build=true
# 生成并应用 K8s 清单(扩展已写入 target/kubernetes/)
kubectl apply -f target/kubernetes/kubernetes.yml
原生镜像 + distroless 基础镜像,最终镜像往往只有 50–80MB,比 Fat Jar 镜像小一个数量级,拉取与调度都更快。部署到 Kubernetes 后,配合 HPA 按 CPU 弹性伸缩,资源成本显著下降。
八、用 GitHub Actions 做原生构建 CI
原生编译较慢(数分钟),适合放在 CI 而非本地反复跑。下面是一段最小可用的 workflow,借助 GitHub Actions 缓存 Maven 与 GraalVM 提升速度:
name: native-ci
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: graalvm/setup-graalvm@v1
with:
java-version: '21'
distribution: 'graalvm'
native-image: true
- run: ./mvnw package -Dnative
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: registry/quarkus-demo:${{ github.sha }}
九、生产落地建议与避坑
原生镜像不是银弹,落地时注意几点:① 反射、动态代理、序列化需要在构建期被”看到”,第三方库若不支持需手动写 reflect-config.json;② 避免运行期大量 Class.forName 与字节码增强;③ 先用 JVM 模式跑通逻辑,再切原生验证;④ 监控仍可用 Micrometer + OpenTelemetry 接入现有体系。遵循这些,Quarkus 能稳稳成为你云原生 Java 微服务的主力框架。



