Quarkus深度解析:Foojay播客访谈精华
[LOADING...]
Quarkus 深度解析:Foojay 播客精华回顾
最近,我有幸受邀参加 Foojay 播客,深入探讨了 Quarkus。
这场对话涵盖了诸多方面,从 Quarkus 的独特之处,到 JVM 模式与原生模式之间的实际权衡。
本文提炼了讨论中的核心问答,并稍作编辑以提升可读性。
如果你一直在关注本系列博客,请注意,关于“用 Quarkus 构建你自己的技术栈”的第三部分即将发布。
请将本文视为一个额外福利,它将播客内容浓缩为便于阅读、参考和分享的格式。
什么是 Quarkus?
Quarkus 是一个面向任何云(包括超大规模云)的云原生 Java 框架,它将效率与成本节约和出色的开发者体验融为一体。
它具备开发模式与持续测试等创新特性,同时保持了 Java 闻名于世的企业级稳定性。
Quarkus 专为需要快速冷启动、高密度部署以及高效工作流(含热重载)的云原生 Java 开发者而设计。
同时,它保留了标准 API,并提供在 JVM 上运行或原生模式下运行的选择。
Quarkus 与 Spring、Micronaut 等其他框架相比如何?
广义上讲,Quarkus、Spring Boot 和 Micronaut 都服务于企业级市场,但 Quarkus 因其对云原生默认配置的专注而脱颖而出。
虽然 Spring Boot 传统上依赖运行时反射和类路径扫描,但近年来已逐步支持 AOT(提前编译)处理。相比之下,Quarkus 从一开始就围绕构建时处理和 GraalVM 原生编译进行设计,从而带来更快的启动速度和更低的内存占用。
从日常使用角度看,Quarkus 通过开发模式和热重载等功能增强了开发者体验,能在代码变更时提供即时反馈,无需漫长的重新构建或重启。
此外,Quarkus 通过使用 Eclipse Vert.x 集成了命令式与反应式两种编程模型,同时仍遵循 MicroProfile 和 Jakarta EE 等标准。
Quarkus 是否因为更新而更现代化?
Quarkus 比许多成熟的 Java 框架更新,但“更新”并不自动意味着“更现代化”。
实际上,其设计避开了遗留约束,远离了那些不适合云原生部署的旧模式。
相反,Quarkus 专注于构建时处理与精简的开发者循环。
它还借鉴了早期框架的经验教训,在其高效的扩展模型和配置中可见一斑。
Quarkus 之所以感觉更现代,不仅因为它更新,更在于它从根本上拥抱了云原生范式。
Quarkus 会取代 JVM 吗?
不,它不会取代 JVM。
在 JVM 模式下,Quarkus 像其他 Java 框架一样运行在 JVM 上,同时利用其 GraalVM 集成。
在原生模式下,Quarkus 将应用程序编译为原生可执行文件,因此运行时不需要 JVM。
这里所说的“运行时”指的是启动应用程序并整合框架、配置以及应用程序所依赖的运行时服务的执行栈。
换句话说,Quarkus 作为一个智能层来管理应用程序生命周期,无论是在标准 OpenJDK 上运行还是作为原生二进制文件运行。
什么是 Quarkus 热重载?
热重载是一项核心的、颠覆性的功能。
在 Quarkus 开发模式下,热重载会在应用程序运行时应用代码、配置和资源变更,因此你可以立即看到结果,无需重建或重启。
它消除了人们通常与 Java 关联的缓慢周转,为企业级 Java 开发带来了类似脚本的工作流。
它不仅仅限于代码变更,因为开发模式还驱动着开发服务(Dev Services),这些服务可以在 Docker 容器中预置数据库或 Kafka 代理等基础设施,并无需额外配置即可连接到你的应用程序。
持续测试功能会在你保存文件后立即在后台运行相关测试。
最近,Quarkus 引入了 Dev MCP(模型上下文协议),允许本地 AI 编码代理连接到正在运行的应用程序,从而为调试和编写代码提供更多上下文。
构建时优化是如何工作的?
构建时优化是 Quarkus 的一种机制,它将成本高昂的启动流程(如扫描类以查找注解、解析配置文件、构建应用程序元模型)转移到构建阶段。
Quarkus 不在每次应用程序启动时重复这些工作,而是在编译时进行一次,并生成包含预计算结果的优化字节码。
这带来四个主要好处:
- 更快的启动速度:因为应用程序启动时跳过了扫描和解析的重活。
- 更低的内存占用:因为最终制品更小更精简,并且仅在初始化阶段需要的库(如解析器)不会在运行时加载。
- 更早的错误检测:因为 Quarkus 会在构建期间捕获配置错误或错误的注解使用,从而快速失败,而不是在运行时崩溃。
- 减少反射:因为 Quarkus 生成代理以避免反射调用,从而提升性能。
这与 JIT 和 AOT 有何不同?
有必要区分构建时优化与即时编译(JIT)以及像 Project Leyden 这样的提前编译(AOT)举措。
通过 JIT,JVM 在应用程序运行时将热代码路径优化为机器码。
Quarkus 的构建时优化则不同:它改进了基线启动速度和内存配置,使应用程序能更快地进入 JIT 预热阶段。
对于像 Project Leyden 这样的 AOT 工作,目标是将常规 JVM 机制(如类加载和堆归档)转移到构建时。
Quarkus 侧重于语义层面的框架优化。
它理解你使用的框架(如 Hibernate 或 Camel),并在 JVM 启动之前就解决它们的依赖连线。
这就是为什么 Quarkus 今天就能在标准 OpenJDK 版本上提供这些好处,而不受 Leyden 时间表及其限制的影响。
其他关键优势是什么?
这里我们可以谈谈 Quarkus 如何将高效的开发者工作流与生产中的运维需求连接起来。
第一天:开发者体验
- 开发服务(Dev Services) 减少了“在我机器上能跑”的问题,通过在 Docker 容器中启动外部服务(如数据库、Kafka 或 Keycloak)并将其连接到应用。
- 这在许多本地开发环境中消除了手动编写 Docker Compose 文件的需求。
- 开发 UI(Dev UI) 随应用程序一起运行,显示配置、活动 bean 和路由,使故障排查更直接。
- 对于 Kubernetes 原生部署,Quarkus 可以生成 Kubernetes 清单文件,并通过 Jib 或 Docker 构建容器镜像,因此开发者无需先学习所有 Kubernetes 细节即可部署。
第二天:运维
- 安全性:Quarkus 通过专用扩展集成了 OIDC(OpenID Connect)和 WebAuthn(无密码认证)等标准。由于 Quarkus 在构建时完成框架工作,它可以通过在部署前移除未使用的代码路径来减少部署后的攻击面。
- 可观测性(指标、日志和追踪):Quarkus 集成了 OpenTelemetry 和 Micrometer,因此指标、分布式追踪和日志关联通常默认即可工作,无需额外设置。
- 容错性:MicroProfile Fault Tolerance 允许开发者通过注解应用断路器、重试或隔板模式,使应用无需自定义代码即可处理常见的网络故障。
Quarkiverse 生态系统
Quarkus 拥有 Quarkiverse 生态系统,这是一个社区扩展目录,提供了大量将 Quarkus 连接到常见 Java 库和平台的扩展。
Quarkus 扩展目录 列出了大量且不断增长的扩展,包括来自 Quarkiverse 的社区贡献。
JVM 模式与原生模式
JVM 模式是大多数团队的首选(或应该是首选)。
与传统技术栈相比,JVM 上的 Quarkus 已经改善了启动时间和内存效率,且无需改变运行时。
原生编译是一种针对特定需求的专用工具,例如非常快的启动和非常严格的资源限制(例如在全栈应用中使用不到 100 MB 的 RAM)。
同时,说原生模式无法处理长时间运行的工作负载是不准确的。
Quarkus 通过在构建过程中应用框架级别的知识来优化原生构建,基准测试显示其性能随时间保持稳定。
在资源受限的云环境中,Quarkus 原生应用可以以最小的 CPU 和内存提供强大的吞吐量,具体数值取决于工作负载、JDK 版本和配置。
还有其他 AOT 方法,例如快照(snapshotting),它捕获已准备好的进程镜像并快速恢复,包括 Project Leyden 和 AWS Lambda SnapStart 中的工作。
这些方法能显著缩短启动时间,接近原生水平,但无法实现同样的内存缩减。
实践中,对于计算密集型工作负载,JVM 通常提供最佳的峰值吞吐量,而在资源受限的环境中,原生模式提供更好的密度和内存效率。
Quarkus 如何帮助降低云成本?
Quarkus 通过资源密度和弹性来降低云开支。
由于 Quarkus 应用程序通常占用更少的 RSS 内存(进程实际使用的内存),团队可以在相同的 Kubernetes 节点上运行更多 Pod,或者迁移到更小的节点。
这通常意味着更少的节点、更小的实例规格,或者两者兼有。
具体来说,与更重的 Java 技术栈相比,你通常可以在更小的实例类型上运行 JVM 模式的 Quarkus 服务,同时仍能处理真实流量。
这在你考虑自动扩缩之前就已经降低了基础成本。
接下来是 Serverless 方面。
当启动时间很短时,冷启动的代价就变小了,因此团队更积极地缩放到零。
这减少了闲置容量的费用,因为你主要只在服务实际运行时付费。
Vert.x 与虚拟线程是互补还是竞争?
它们高度互补,而非竞争。
虚拟线程解决了并发问题:它允许你编写简单的阻塞风格代码,以非常少的内存处理大量并发。
然而,虚拟线程并未解决 I/O 问题。
你仍然需要一个高性能的非阻塞层来高效地在网络上传输字节。
Vert.x 提供了这一基础。
它充当 Quarkus 的底层 I/O 引擎,通过多反应器模式(非阻塞事件循环)管理网络交互。
当虚拟线程在 Quarkus 中执行网络调用时,底层 I/O 可以由 Vert.x 的非阻塞层处理(取决于所使用的 API 和扩展)。
虚拟线程会廉价地挂起,而 Vert.x 处理繁重的工作,并在数据准备好时恢复。
结果:你获得了阻塞代码的开发者体验,同时拥有反应式栈的运行时性能。
结论
本文捕捉了 Foojay 播客对话的精髓。
Quarkus 将构建时优化、高效的开发者循环以及云原生运维特性融合在一个框架中。
无论你是从 JVM 模式开始,看重其吞吐量和诊断能力,还是在密度和启动延迟至关重要时使用原生模式,Quarkus 都能适应工作负载。
有关本文涵盖主题的更多深度内容,请参阅本系列之前的文章:
敬请期待下一部分,我们将探讨如何使用 Quarkus 构建自己的技术栈。
本文 Quarkus 深度解析:Foojay 播客精华回顾 最初发布在 foojay 上。