2019 年,Quarkus 在企业 Java 生态系统中引起了不小的轰动。Quarkus 到底是什么?它与市场上的其他技术有何不同?Quarkus 为我或我的组织提供了什么帮助?让我们一起找出答案。
更多 Quarkus 的项目进展和路线图,敬请关注 QCon 全球软件开发大会(北京站)2020 。届时红帽高级软件工程师冯征将进一步介绍 Quarkus 框架设计和特点,利用 Quarkus 进行应用开发、通过 Kubernetes 进行应用部署的实践案例。对 下一代面向云原生的编程框架 Quarkus 感兴趣的读者不要错过。
Quarkus 项目自称是超音速亚原子 Java。这是真的吗?这是什么意思?我们需要了解下软件开发的现状,才能更好地理解 Quarkus 项目背后的动机。
以前部署应用程序的方法是使用物理硬件。购买了物理机,我们就预先为硬件需求付了款。我们已经进行了投资,因此,使用所有的或者只是少量的机器资源都没有关系。在大多数情况下,只要能够运行应用程序,我们就不会关心其他事情了。然而,云正在改变我们开发和部署应用程序的方式。
因为云上按需付费,所以我们对硬件的使用越来越讲究。如果应用程序启动需要 10 秒,那么即使应用程序还没有准备好供其他人使用,我们也必须为这 10 秒付费。
你还记得第一个 Java 版本是什么时候发布的吗?请允许我提醒你一下,那是在 1996 年。那时还没有云。事实上,云是几年后才出现的。Java 显然不适合这种新模式,必须进行调整。但是,这么多年来,我们都是在使用物理机,成本不像在云上那么重要,我们怎么才能改变这种模式呢?
多年来,许多 Java 库和框架的发展方式都是在运行时执行一组增强。这是一种安全、方便的向代码添加功能的声明性方法。你需要依赖注入吗?当然!使用注解。你需要事务吗?当然!使用注解。实际上,使用这些注解,你可以编写许多代码,运行时将提取并处理它们。但这有一个缺点,运行时需要扫描类路径和类以获取元数据。这是一个消耗时间和内存的昂贵操作。
Quarkus 通过将昂贵的操作(如字节码增强、动态类加载、代理等)转移到编译时解决了这个问题。其结果是一个消耗内存和 CPU 更少、启动速度更快的环境。这非常适合云的应用场景,对于其他用例也非常有用。无论是什么样的环境,每个人都将受益于更少的资源消耗。
你听说过或使用过 CDI、JAX-RS 或 JPA 之类的技术吗?Quarkus 技术栈就是由这些已经存在了好多年的技术组成的。如果你知道如何使用这些技术进行开发,那么你就会知道如何开发 Quarkus 应用程序。
你能读懂下面的代码吗?
复制代码
@Path("books") @Consumes(APPLICATION_JSON) @Produces(APPLICATION_JSON) public class BookApi { @Inject BookRepository bookRepository; @GET @Path("/{id}") Response get(@PathParam("id")Long id) { returnbookRepository.find(id) .map(Response::ok) .orElse(Response.status(NOT_FOUND)) .build(); } }
恭喜,你已经有了自己的第一个 Quarkus 应用!
Quarkus 编程模型建立在经过验证的标准之上,无论是官方标准还是事实标准。目前,Quarkus 对 Hibernate、CDI、Eclipse MicroProfile、Kafka、Camel、Vert.x、Spring、Flyway、Kubernetes、Vault 等技术提供了一等支持。当使用 Quarkus 时,你从第一天开始就会很有效率,因为你真的不需要学习新技术。你只需要使用过去 10 年一直存在的东西。
你打算使用一个不在 Quarkus 生态系统中的库吗?除非你想在 GraalVM Native 模式下运行它,否则很有可能不需要任何额外的设置就可以直接使用。如果想更进一步,那么你可以轻松地实现自己的 Quarkus 扩展,为特定的技术提供支持,并丰富 Quarkus 生态系统。
那么,你可能会问,是否有什么东西还需要开发人员自己探索。实际上是有的。你需要在你的项目中使用 Quarkus 提供的一组特定的依赖项。别担心,Quarkus 同时支持 Maven 和 Gradle。方便起见,你可以在 Quarkus starter 页面 中生成一个框架项目,并选择要使用哪些技术。将它导入到你喜欢的 IDE 中,就可以开始了。以下是一个使用 JAX-RS with RESTEasy 和 JPA with Hibernate 的 Maven 示例项目:
复制代码
<?xml version="1.0"?> <projectxsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>org.acme</groupId> <artifactId>code-with-quarkus</artifactId> <version>1.0.0-SNAPSHOT</version> <properties> <compiler-plugin.version>3.8.1</compiler-plugin.version> <maven.compiler.parameters>true</maven.compiler.parameters> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <quarkus-plugin.version>1.3.0.Final</quarkus-plugin.version> <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id> <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id> <quarkus.platform.version>1.3.0.Final</quarkus.platform.version> <surefire-plugin.version>2.22.1</surefire-plugin.version> </properties> <dependencyManagement> <dependencies> <dependency> <groupId>${quarkus.platform.group-id}</groupId> <artifactId>${quarkus.platform.artifact-id}</artifactId> <version>${quarkus.platform.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <dependencies> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-junit5</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.rest-assured</groupId> <artifactId>rest-assured</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-hibernate-orm</artifactId> </dependency> <dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-resteasy-jsonb</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>io.quarkus</groupId> <artifactId>quarkus-maven-plugin</artifactId> <version>${quarkus-plugin.version}</version> <executions> <execution> <goals> <goal>build</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>${compiler-plugin.version}</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>${surefire-plugin.version}</version> <configuration> <systemProperties> <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager> </systemProperties> </configuration> </plugin> </plugins> </build> </project>
你可能已经注意到,大多数依赖项都是从 groupId io.quarkus 开始的,而且它们不是 Hibernate、Resteasy 或 Junit 的常见依赖项。
现在,你可能想知道,为什么 Quarkus 围绕这些流行库提供自己的包装器版本。其原因是为了在这些库和 Quarkus 之间提供一个桥梁,以便在编译时解析运行时依赖项。这就是 Quarkus 的神奇之处,其项目启动速度快,占用内存少。
这是否意味着你只能使用特定于 Quarkus 的库?绝对不是。你可以使用任何你想用的库。你可以在 JVM 上像往常一样运行 Quarkus 应用程序,这样就不会有任何限制。
也许你已经听说过 Oracle 实验室的 GraalVM 项目。本质上讲,GraalVM 是一个通用的虚拟机,可以运行多种语言的应用程序。它最有趣的其中一个特性是,可以在原生镜像中构建应用程序并以更快的速度运行它!实际上,这意味着你有了一个可执行文件,应用程序所需的所有依赖项都是在编译时解析的。它不是在 JVM 上运行的——它是一个普通的可执行二进制文件,但是包含所有必需的组件,比如内存管理和线程调度,从一个特别的虚拟机 Substrate VM 运行你的应用程序。
方便起见,Maven 示例项目已经具备了将你的项目构建为原生项目所需的设置。你需要在系统中安装 GraalVM 和 native-image 工具。请按照以下 说明 操作。之后,只需像其他任何 Maven 项目一样构建,但是使用本机配置文件:mvn verify -Pnative。这将在目标文件夹中生成一个二进制运行器,你可以使用./project-name-runner 像运行任何其他二进制文件一样运行它。以下是我机器上的一个运行器输出样例:
复制代码
[io.quarkus](main)code-with-quarkus1.0.0-SNAPSHOT(powered by Quarkus1.3.0.Final)startedin0.023s.Listeningon:http://0.0.0.0:8080 INFO[io.quarkus](main)Profileprodactivated. [io.quarkus](main)Installedfeatures:[agroal, cdi, hibernate-orm, narayana-jta, resteasy, resteasy-jsonb]
注意到启动时间了吗?只有 0.023 秒 。是的,我们的应用程序不大,但仍然令人印象深刻。即使是真实的应用程序,你也会看到毫秒级的启动时间。你可以在他们的 网站 上了解更多关于 GraalVM 的信息。
我们已经看到,Quarkus 可以帮助你的公司成为云原生公司。太棒了。但是开发人员呢?我们都喜欢闪亮的新东西,我们也超级懒。Quarkus 为开发者做了哪些其他技术做不到的事情?
那么,在不使用外部工具或复杂技巧的情况下,热重载是否也能正常工作呢?是的,这是真的。在 Java 诞生 25 年后,我们现在有了一种更改代码的可靠方法,并且通过简单的刷新就可以查看这些更改。这也是通过 Quarkus 的内部工作方式实现的。一切都是代码,所以你不必再担心那些使热重载变得困难的事情。这是一个很简单的操作。
要做到这一点,你必须在开发模式下运行 Quarkus。只要运行 mvn quarkus:dev 就可以了。Quarkus 将启动,你可以自由地对代码进行更改并立即看到它们。例如,你可以更改 REST 端点参数、添加新方法和更改路径。一旦你调用它们,它们将被更新以反映你的代码更改。这很酷吧?
所有这一切似乎好得令人难以置信,但 Quakus 真的准备好投入生产环境了吗?是的。
许多公司已经采用 Quarkus 作为他们的开发 / 运行环境。Quarkus 有一个非常快的发布周期(每隔几周),以及一个强大的开源社区,它可以帮助 Java 社区中的每个开发人员,无论他们是刚刚开始使用 Quarkus,还是已经是一个高级用户。
要查看这个 示例应用程序 ,你可以下载或克隆它。你还可以阅读一些讲述 采用故事 的博文,更好地了解 Quarkus 的使用体验。
在官方发布一年后,Quarkus 已经发布了 1.3.1.Final 版本。这个项目做了大量的工作来帮助公司和开发人员编写云原生应用程序。
我们不知道 Quarkus 能走多远,但有一件事可以肯定:Quarkus 震撼了整个被 Spring 主宰着的 Java 生态系统。我认为,Java 生态系统要想胜出,就需要提供多种可以相互推动的产品,并通过创新保持产品的竞争力。
Roberto Cortez是一位热诚的 Java 开发人员,拥有超过 10 年的经验。他参与开源社区,帮助其他人传播 Java 技术知识。他经常在 JavaOne、Devoxx、Devnexus、JFokus 等会议上发言。他领导着 Coimbra JUG,并在葡萄牙创办了 JNation 会议。在业余时间,他会和朋友出去玩,玩电脑游戏或与家人呆在一起。
Getting Started with Quarkus