vlambda博客
学习文章列表

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

Introduction to Quarkus Core Concepts

Java 在 20 多年前被引入开源社区。从那时起,我们再也想不出有哪家大型 IT 公司或组织不使用 Java。出于这个原因,Java 通常被视为一种企业语言,这本身并不是一件坏事:Java 是企业标准,它是一种极其成熟的语言,具有围绕它的巨大的工具和库生态系统,并且仍然是世界上开发人员使用最多的语言。

然而,IT 行业的 20 年是一段相当长的时间。从一开始,Java 就经历了一系列优化,并肩负着保持与早期版本向后兼容的重任。然而,如今,随着云、容器、微服务和响应式编程等新标准的兴起,IT 环境发生了显着变化。我们是否仍然需要使用 Java 来解决最新的应用程序架构并达到更高水平的生产力和效率?是的!本书承诺在向您介绍 Quarkus 的同时做到这一点,这是一个 Kubernetes 原生框架,它将把超音速、亚原子 Java 带到新的高度!

在本书的第一部分,我们将学习如何使用简单的工具创建 Quarkus 应用程序,同时使用开发环境对其进行编码、执行和调试。完成所有绿色条后,我们将专注于高级主题,向您展示如何组合多个 Quarkus 扩展来生成无服务器基础架构。

就本章而言,我们将通过涵盖以下主题快速了解 Quarkus 技术:

  • An overview of the IT landscape, showing the benefits of cloud-native applications and microservices
  • The basics of the Quarkus architecture
  • Installing the required software (GraalVM to compile code natively and a development environment)

From the big data hype to Kubernetes

大约 10 年前,IT 行业最热门的话题是大数据每家大型企业都在竞相利用海量但据称可管理的数据孤岛的神秘力量。有了大数据,没有什么问题是不可克服的,所有的预测都会得到满足。

但最近,这些预测似乎已经褪色,而 IT 行业最保守的秘密是大数据已死——至少我们所知道的情况如此。这并不意味着数据的数量或增长已经崩溃——或者相反。只是底层技术发生了变化,这意味着使用大数据的应用程序架构也发生了变化。

以 Hadoop 为例,它一直是大数据炒作的标志。它是根据一组在短时间内发生巨大变化的假设设计的。其中一个假设是,为了处理大量数据,网络延迟是邪恶的,云原生存储根本不是一种选择。当时,大部分 IT 行业数据都在本地,因此重点是避免在大量信息中移动。这意味着为了有效地计算数据,数据将被放在一起。

今天,这种情况发生了很大变化:大多数应用程序仍然使用大量数据,但数据现在是动态处理的。也就是说,我们现在流式传输数据,而不是多次处理整个数据集。

除此之外,网络延迟障碍已不再是云提供商的问题,甚至有多种云源可供选择。此外,公司现在可以选择在本地部署自己的私有云,从而带来新的场景,例如混合云。

因此,真正改变的焦点是:今天,大数据不仅意味着大量数据集,还意味着大量数据的灵活存储选项。

这就是容器,特别是 Kubernetes 适合的地方。简而言之,您可以将容器视为一个打包的应用程序,其中仅包含运行它所需的库,而 Kubernetes 就像一个编排系统,它使确保所有容器在管理其生命周期时都有适当的资源。

Kubernetes 使用 Docker 运行映像和管理容器。但是,Kubernetes 也可以使用其他引擎(例如,rkt)。由于我们将在 Kubernetes 之上构建应用程序,因此我们将在下一部分简要概述其架构。

The Kubernetes architecture in a nutshell

Kubernetes 的架构围绕着一个松散耦合、灵活的服务发现机制的概念。与大多数其他分布式中间件平台一样,Kubernetes 集群由一个或多个主节点和多个计算节点组成。 下图描绘了 Kubernetes 集群的高级视图:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

Kubernetes 主节点本质上构成了集群的大脑。他们负责管理整个集群、公开 API 和调度部署。 Kubernetes 节点(上图右侧)包含在称为 Pod 的组件中运行应用程序所需的服务。

每个主节点包含以下组件:

  • API Server: This synchronizes and validates the information running in Pods and services.
  • etcd: This provides consistent and highly available storage for the cluster data. You can think of etcd as the brain's shared memory.
  • Controller Manager server: This checks for changes in the etcd service and uses its API to enforce the desired state.
  • HAProxy: This can be added when we're configuring HA masters to balance loads between several master endpoints.

Kubernetes 节点(简称 节点)可以被视为 Kubernetes 集群的主力。每个节点都向您的应用程序公开一组资源(例如计算、网络和存储)。该节点还附带用于服务发现、监控、日志记录和可选附加组件的附加组件。在基础架构方面,您可以将节点作为虚拟机 (VM) 在云环境中或在数据中心运行的裸机服务器之上运行。< /跨度>

每个节点包含以下组件:

  • Pod: This allows us to logically group containers and pieces of our application stacks together. A Pod acts as the logical boundary for such containers with shared resources and contexts. Pods can be scaled at runtime by creating Replica sets. This, in turn, ensures that the required number of Pods is always run by the deployment.
  • Kubelet: This is an agent that runs on each node in the Kubernetes cluster. It makes sure that the containers are running in a Pod.
  • Kube-Proxy: This maintains network rules on nodes to allow network communication between Pods.
  • Container Runtime: This is the software that is responsible for running containers. Kubernetes supports multiple container runtimes (such as Docker, containerd, cri-o, and rktlet).

现在我们已经介绍了 Kubernetes 架构的基础知识,让我们看看它可以为您的组织带来的最大优势。

Benefits of using Kubernetes

Kubernetes 可以为您的组织带来的优势如下:

  • Kubernetes greatly simplifies container management. As you have learned, when using Kubernetes, there's no need to manage containers directly. Instead, you just to have manage Pods. In order to have your applications available in your Pods, Kubernetes introduced an abstraction called a service. It defines a logical set of Pods with their IP address. This level of abstraction enhances fault tolerance and reduces downtime by launching containers on different machines.
  • Kubernetes speeds up the process of building, testing, and releasing software by supporting a wide range of programming languages (Java, Go, Python, and so on) and offering advanced deployment features (automated rollouts and rollbacks, canary deployments, and more). This makes it a lot easier to configure effective Continuous Integration/Continuous Delivery (CI/CD) pipelines for your software.
  • Kubernetes provides the fastest and least costly horizontal scalability for your pods, so when the number of users for your application increases, you can configure the replication service to fire new Pods and balance the load across them to avoid downtime.
  • It's worth mentioning that Kubernetes is able to manage both stateless and stateful applications, because it allows ephemeral storage and persistent volumes. It also supports a number of storage types, such as NFS, GlusterFS, and cloud storage systems. Furthermore, a persistent volume (PV) life cycle doesn't depend on any pod using it, so you can keep the data as long as you need it.

在您的行业中使用 Kubernetes 作为服务编排器的好处是显而易见的,但下一个问题是,我们如何编写服务以充分利用该架构?我们仍然可以使用我们在过去几年中学到的相同标准来编写我们的应用程序吗?下一节将解决这个难题。

From Java EE to MicroProfile

Java 企业版 (EE) 已达到卓越的成熟度,并在 IT 企业中得到广泛采用。 Java EE 应用程序通常打包为一个整体应用程序并部署在一个应用程序服务器中,该服务器可以托管多个应用程序。

单体应用程序可以被认为是一个独立的应用程序,它包括用户界面和运行应用程序所需的业务组件。

这种方法已被广泛使用多年。原因很简单:单片应用程序在概念上易于开发和打包,因为所有内容都包含在一个包中,并且可以使用单个 IDE 进行编辑。此外,扩展单体应用程序很简单:您需要做的就是扩展单个组件。

因此,传统的企业应用程序编码方式会产生大量应用程序,这些应用程序本应作为长期运行的进程提供,并且需要应用程序服务器来管理它们的高可用性(哈)。反过来,需要一些其他工具来管理发生故障时的服务器重新启动并检查系统的整体健康状况。

随着基于服务器的单体应用程序不断增长,一些缺点变得明显,如下所示:

  • Difficult to maintain: This is due to the size of the applications, which makes it complex to create a patch for them.
  • Limited scalability: You can scale the whole application, not the single services.
  • Longer release cycles: Any changes that are made to the code require that we deploy the whole application, which complicates things when multiple teams are working on the same application.
  • Less isolation: Deploying multiple applications in an application server can potentially lead to a whole system failure from a single application misbehaving.
  • Slower startup: The startup time of a full monolithic stack is ill-famed to be slow, especially if multiple applications are deployed at the same time and potentially competing for the same resources.
  • Complex monitoring: It is harder to monitor and tune the activity of a single monolithic application which delivers a myriad of metrics.
  • More complex CI/CD: Configuring a CI/CD pipeline for multiple monolithic applications is equally as hard.

在这种情况下,一种名为微服务的新范式围绕一个简单但并不新鲜的想法而出现。微服务背后的主题是,对于某些类型的应用程序,一旦它们被拆分成更小且可组合的部分,就更容易构建和维护它们。在基于服务的架构中,我们不再需要以几周或几个月来衡量应用程序的正常运行时间,因为我们可以在需要时激活我们的服务。因此,时间因素可以小到几分钟或几秒。

在这样的架构中,每个组件都有自己的生命周期,从开发到测试,最终的应用程序只是所有这些单个组件的组合。这种方法标志着对单体应用程序的明智背离,在这种应用程序中,所有东西都是作为一个单元构建和测试的。

作为一组较小的模块化组件构建的应用程序更易于理解,更易于测试/调试,并且更易于在应用程序生命周期内进行维护。微服务架构通过减少部署生产改进所需的时间来利用公司的敏捷性。这种方法已经过尝试和测试,并且由于以下原因更胜一筹:

  • Increased resilience: The microservice architecture increases the system's overall capability to withstand any kind of unexpected failures or faults of components or networks by spinning up another component, even as the remaining application continues to function.
  • Developer independence: By working in smaller teams in parallel, you can speed up the work that's being done, especially for large enterprise applications that are composed of teams that are geographically and culturally diverse.
  • Scalability: Fewer resources are demanded by smaller components. This means we can easily scale them to meet the increasing demand of only that specific component.
  • CI/CD life cycle automation: Single components fit smoothly into CD pipelines and scenarios that have complex deployment.
  • Simpler mapping with the business: Microservice architectures are easier to map with the business domain logic since they have increasing independence and transparency across the organization.

为了从我们的软件即服务 (SaaS) 中获得最佳结果,需要一种方法。在下一节中,我们将讨论十二要素应用程序方法,开发人员推荐这种方法可以顺利工作和交付专注于微服务的应用程序。

The Twelve-Factor App methodology

2011 年,Heroku 创始人 Adam Wiggins 发布了十二要素应用程序方法,该方法很快成为构建软件即服务(SaaS) 基于他们自己的经验。这种方法不是任何编程语言独有的,而是与微服务架构兼容,并且基于容器和 CI/CD 管道。让我们来看看这12个因素:

  • Code base: You should build your application on top of one code base, tracked by a Version Control System (VCS). You should rely on a base repository for an individual application to ease CI/CD pipelines. It follows that deployments should be automatic so that everything can run in different environments without anything needing to be done.
  • Dependencies: Don't push any dependencies to your project code base. Instead, use a package manager so that you will have all the dependencies synced across your environments to make sure you reproduce the same behavior.
  • Config: Store your configuration in environment variables. The configuration should be well parted from the code so that the configuration varies in terms of where the application has been deployed.
  • Backing services: Services should be easily interchangeable so that you can manage your backing services as attached resources. You must be able to easily exchange the backing services from one provider to another without changing your code. This maximizes portability and helps maintain your system.
  • Build, run, release: There should be a clear and strict separation between the build, release, and run stages. You can achieve this by assigning a unique release ID and allowing releases to roll back. The automation between these stages should be as easy as possible.
  • Stateless processes: This factor lies at the core of the microservices architecture. You should not be introducing state into your services. Any data that needs to be persisted must be stored in a backing service, typically a database or another storage.
  • Port binding: By this factor, your application should be completely self-contained. It should not depend on the runtime startup of a web server into the execution environment to create a frontend service. The web app should make HTTP applications as a service available by binding the service to a port.
  • Concurrency: You should break down your application into much smaller pieces. Smaller, well-defined apps allow you to scale out as needed to handle varying loads. You should be able to individually scale the single component.
  • Disposability: You should aim to maximize the robustness of your systems by coding applications with a fast startup and graceful shutdown. This means you should be able to handle unexpected failures. A recommended approach consists of using a robust async backend that returns notifications when failures occur.
  • Dev/prod Parity: You should aim to keep the development, staging, and production phases similar and homogeneous to limit deviation and errors. This also implicitly encourages a DevOps culture where software development and operations are unified.
  • Logs: Logging is a key factor for debugging and monitoring your application's general health. The place where logs are stored shouldn't be a concern for developers. Instead, these logs should be treated as a continuous stream that's being separately captured and stored by a service.
  • Admin Processes: In many cases, developers perform one-off administrative or maintenance tasks, such as database migrations, application patching, or one-time script execution for the app. It is essential to run one-off admin processes in an environment that is similar to the regular long-running processes of the app.

尽管前面的一些模式乍一看似乎微不足道,但随着您的服务开始增长,它们成为必不可少的构建块。因此,在设计微服务应用程序时,请记住,大多数挑战不仅与编码有关,还与基础知识错误有关。事实上,即使是优秀的团队,如果没有包含 DevOps 和关键构建块(例如十二要素应用程序方法)的文化,也会在微服务上失败。

The MicroProfile initiative

在讨论了微服务的方法之后,我们现在将介绍与可用于开发微服务的特定 API 相关的一些方面。

虽然乍一看,Java 和微服务似乎并不真正匹配,但放弃整个 Java EE 生态系统(更名为 Jakarta EE 并转移到 Eclipse 基金会)将是一个坏主意已创建。在重用 Java EE 编码微服务方面已经付出了很多努力。

事实上,包括 IBM、Red Hat 和 Payara 在内的许多主要供应商已经提供了一个轻量级和可扩展的运行时来支持 m微服务 和云部署。 MicroProfile.io 计划中自然而然地在他们的个人努力之后进行了公开合作。

MicroProfile 组件建立在 Java EE 模型之上,因此可以自然地过渡到微服务开发。这意味着您将能够重用多年来积累的 Java EE 宝贵知识,以灵活地使用多个供应商规范来定义应用程序需求。

在其初始版本中,MicroProfile 计划仅包含 Java EE API(JAX-RS 2.0、CDI 1.2 和 JSON-P 1.0)的小幅缩减。

然而,在很短的时间内,已经添加了新的 MicroProfile 项目。仅在 2018 年,我们就看到了 MicroProfile 1.3、1.4、2.0 和 2.1 以及其中包含的项目的出现。 MicroProfile 计划的当前版本通过不属于 Java EE 的功能扩展了标准,例如配置、弹性、监控、健康检查和分布式跟踪。

下图根据最新规范(在撰写本书时)描述了 MicroProfile 项目的构建块:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

然而,在开发复杂的企业应用程序时,单单 MicroProfile 是远远不够的。例如,它不包括开箱即用的持久性、事务或 安全套接字层 (SSL) 管理 API。出于这个原因,我们需要一个利用具有可扩展功能的 MicroProfile API 的框架,并且从管理的角度来看,它可以由将成为新应用程序服务器的 Kubernetes 进行编排。

Quarkus – a Kubernetes-native Java framework

微服务架构的主要挑战之一是服务的激增会增加系统的复杂性,除非你有一个有效的框架来编排它们。 此外,如果没有一个集中的功能身份验证、数据管理和 API 网关,微服务架构的优势因这些挑战而失效。

在这个意义上,Kubernetes的到来是IT模式的真正革命。借助基于 Kubernetes 的编排,您可以通过以动态方式管理和调度微服务来提高效率和资源利用率。 这还增加了高级弹性级别。您可以根据需求变化继续运营,无需担心容器故障。为了封闭循环并统一所有组件,我们需要一个经过专门考虑的框架来在这种架构中工作。让我们见见 Quarkus。

在管理云原生企业应用程序方面,Quarkus 成为一等公民,并且具有许多惊人的功能,可以实现以前无法实现的场景。 如您所见在接下来的部分中,Quarkus 能够从 Java 类构建精简的本机代码,并从中创建可以在 Kubernetes 或 OpenShift 之上运行的容器镜像。 Quarkus 还利用了您多年来一直使用的最佳 Java 库,例如 RESTEasy、Hibernate、Apache Kafka、Vert.x 等等。让我们更详细地看一下这个框架的亮点。

Native code execution

在 Java 的悠久历史中,曾多次尝试过原生代码执行,但从未得到开发人员的广泛采用。首先,它需要一些外部工具,因为平台供应商没有提供开箱即用的工具。对于单体应用来说,native 执行的优势很小,因为从长远来看,由于 Hot Spot 技术的进步,Java 的速度可以变得更接近 Native 执行(前提是你愿意为更慢的应用买单)引导程序)。

尽管如此,在微服务场景中,启动一堆原生服务起着至关重要的作用,即使优化几秒或几分之一秒也能发挥巨大的作用。同样,如果您的目标是达到最高 内存密度要求、最大请求吞吐量以及一致的 CPU 性能,Quarkus 的本机执行非常适合。

另一方面,您可以使用纯 Java 字节码顺利过渡到 Quarkus,仍然可以交付具有高内存密度要求、出色的 CPU 原始性能、高级垃圾收集策略、大量库或需要标准的监控工具的应用程序JDK,以及无处不在的一次编译,到处运行

下表总结了使用 Quarkus 进行开发时在原生应用程序和 Java 应用程序之间进行选择的一些典型用例:

Quarkus Native applications Quarkus Java applications
Highest memory density requirements High memory density requirements
More consistent CPU performance Best raw performance (CPU)
Fastest startup time Fast startup time
Simpler garbage collection Advanced garbage collection
Highest throughput A large set of libraries and tools that only work with JDK
No JIT spikes Compile once, run anywhere

从这张图可以看出,Quarkus 是一个突破,因为它利用了本机代码执行,同时保留了使用 OpenJDK 运行服务的能力,并在需要时使用 Hot Spot 丰富的动态代码执行能力。

Container first

正如预期的那样,Quarkus 最有前途的功能之一是能够 自动 从您的应用程序中生成容器映像。本机应用程序的最小占用空间经过优化,可在容器内运行。

为您的原生应用程序生成容器镜像还可以解决与原生执行相关的一个常见缺陷,即在使用不同操作系统完成构建时潜在的冲突或错误。由于容器封装了您选择的操作系统,因此您可以为您的应用程序提供容器安全的原生构建,而不会遇到崩溃转储或臭名昭著的蓝屏场景的风险。

Unifying the imperative and Reactive Programming models

大多数 Java 开发人员都熟悉命令式编程模型,该模型转换为用于修改对象状态的指令序列。另一方面,异步编程由于其固有的复杂性和缺乏用于传播异步更改的可靠模式,一直是 Java 开发人员面临的挑战。在这种情况下,一种称为反应式编程的范式因其能够将异步编程模式与数据流和变化的传播结合起来而广受欢迎。

Quarkus 的设计初衷就是将这两种模型统一在同一个平台上,这样您就可以利用这两种编程模型的优势并在您的 IT 组织中使用它们。

Coding that sparks joy

如果使用起来过于复杂并且需要大量的编码和配置来完成即使是很小的功能,即使是最强大的可用框架也不会获得广泛采用。

正如我们从 Spring Boot 的成功中了解到的那样,开发人员使用不需要您在设置或配置上花费大量时间的框架提高了工作效率。 Quarkus 开箱即用,提供以下功能:

  • A unified configuration that can be easily maintained in a single property file
  • A large set of defaults so that you can actually write applications, even with no configuration at all

除此之外,您还可以拥有非凡的功能,例如:

  • Live reload of applications, without any third-party plugins
  • Straight to container generation with native executables
  • Simplified testing by adding testing extensions built specifically for Quarkus

Best-of-breed Java libraries and standards

使开发堆栈成功的标准是各种因素的组合,例如活跃的贡献者数量、顶级行业参与者的高度认可和使用、对知名标准的遵守以及强大和活跃的标准验证器.

在这个问题上,Quarkus 通过利用您已经熟悉的同类最佳库来提供一个有凝聚力的全栈框架,这些库会自动连接在一起以生成最终工件。 Quarkus 扩展包括完整的 Eclipse MicroProfile 堆栈、持久性 API (JPA)、事务管理器 (Narayana)、反应式框架 (Vert.x)、异步事件驱动的网络应用程序框架 k (Netty) 等等。

Quarkus 还包括一个扩展框架,第三方组件作者可以利用它来扩展该框架。 Quarkus 扩展框架大大降低了让第三方框架在 Quarkus 上运行并编译为原生二进制文件的复杂性。

Quarkus architecture

现在我们了解了 Quarkus 的一些亮点,让我们更深入地了解一下这个框架的架构。

在 Quarkus 的核心,有一个 core 组件,它在构建阶段完成了重写我们的应用程序的艰苦工作,以便可以生成超级优化的本机可执行和 Java 可运行的应用程序。为此,Quarkus core 需要一组工具的配合:

  • Jandex: This is a space-efficient Java annotation indexer and offline reflection library that's able to index all runtime visible Java annotations and class hierarchies for a set of classes into a memory-efficient representation.
  • Gizmo: This is a bytecode generation library used by Quarkus to produce Java bytecode.
  • GraalVM: This is a set of components. Every component has a specific function, such as a compiler, an SDK API for the integration of Graal languages and the configuration of native images, and a runtime environment for JVM-based languages.
  • SubstrateVM: This is a subcomponent of GraalVM that allows for the ahead-of-time (AOT) compilation of Java applications of Java programs into self-contained executables.

继续讨论可用的 Quarkus 扩展列表,首先,Quarkus 完全实现了 MicroProfile 规范。 Quarkus 还包括一组用于处理持久性的 Hibernate ORM 扩展、一个事务管理器 (Narayana)、一个连接池管理器 (Agroal),以及其他几个扩展,例如 Apache Kafka、Camel Routes 的 API,以及运行响应式的能力应用程序(Vert.X)。

下图总结了 Quarkus 架构的核心组件,但为了简洁起见,可用扩展的列表不能详尽:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

在介绍了 Quarkus 架构的基础知识之后,不用多说,我们现在将注意力转移到安装构建和运行 Quarkus 应用程序所需的工具上。我们的待办事项清单并不长,很快就会解决。在下一节中,我们将为我们的应用程序安装 GraalVM 和开发环境。

Getting started with GraalVM

要将 Java 代码编译为本机可执行文件,您需要一个名为 GraalVM 的虚拟机扩展。准确地说,GraalVM 是一个通用的虚拟机,可以方便地编译各种语言(如 Python、JavaScript、Ruby 等)的字节码。除此之外,它还允许将这些语言集成到同一个项目中。它还有一些其他功能,其中一个提供 Substrate VM,这是一个允许 AOT 编译以各种语言编写的应用程序的框架。它还允许我们将 JVM 字节码编译为本机可执行文件。

GraalVM 与其他供应商提供的任何其他 JDK 类似,不同之处在于它支持 基于 Java 的 JVM 编译器接口 (JVMCI),并且它使用 Graal 作为其默认 JIT 编译器.因此,它不能执行 Java 代码,还可以执行 JS、Python 和 Ruby 等语言。这可以通过一个名为 Truffle 的语言抽象语法树解释器来完成,该解释器由 Oracle 与 GraalVM 联合开发。

下图描述了 GraalVM 堆栈的高级视图:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

所有这些听起来都很棒,但 GraalVM 也有代价。 Java 的动态特性受到严格限制;例如,有 默认的反射机制,除非已显式注册类/成员以进行反射,否则该机制将不起作用。此外,运行时的类加载、动态代理和静态初始化器最多需要一些更改/解决方法才能工作。

How does Quarkus overcome these limitations? The trick is to move as much framework initialization at build time. During this phase, Quarkus is able to discover which classes need reflection at runtime through metadata discovery (such as annotations). Quarkus uses a set of tools such as Jandex to optimize annotation processing and bytecode generation. Also, to overcome other limitations of GraalVM, Quarkus uses a single-pass, single class loader and programmatically provides compiler hints to enable extensive dead code elimination, thereby substantially cutting down the size of the executable file.

首先,我们将从 https://www.graalvm.org/ 安装 GraalVM。正如您将在 下载 页面中看到的,社区版和企业版 GraalVM 可用。在本书中,我们将使用社区版,因此请下载适合您操作系统的社区版。

Installing GraalVM

有几种方法可以开始使用 GraalVM。您可以下载适用于您的操作系统的压缩二进制文件,也可以从源代码构建它。出于本书的目的,我们将选择前一个选项。安装步骤如下:

  1. Navigate to the Downloads page and choose Community Edition. You will be redirected to the GitHub project where the project is hosted. Download the archive that matches with operating system. Please note that the recommended version of GraalVM to use with Quarkus 1.0.0.final is the version 19.2.1. As a matter of fact, the newer 19.3.0 version does not meet the requirements of Quarkus 1.0.0.final.
  2. Extract the archive to your filesystem.

您应该在提取 GraalVM 的文件夹中具有以下顶级结构:

graalvm-ce-19.2.1/
 ├── 3rd_party_licenses.txt
 ├── ASSEMBLY_EXCEPTION
 ├── bin
 ├── GRAALVM-README.md
 ├── include
 ├── jre
 ├── lib
 ├── LICENSE
 ├── man
 ├── release
 ├── sample
 ├── src.zip

如您所见,GraalVM 的顶层结构与 JDK 非常相似。在 bin 文件夹中, 您将找到许多实用程序和 JDK 工具的替代品。 值得注意的是,当您在 GraalVM 中使用 java 命令时,它会运行 JVM 和默认编译器,即 Graal。 javac 可用于编译您的代码。除此之外,在利用 GraalVM 的本机和多语言功能时,以下命令是必不可少的:

  • js: This command can be executed to run plain JavaScript code if we pass a set of options and the JavaScript filename as an argument.
  • node: This command can be used to run Node.js-based applications. It relies on the npm command to install Node.js modules.
  • native-image: This command takes your Java class(es) and builds an AOT compiled executable or a shared library. It is not included by default in most recent GraalVM installations and you need the gu tools to install it.
  • npm: This is the package manager for Node.js. It puts modules in place so that node can find them and manages dependency conflicts intelligently.
  • lli: This is an LLVM bitcode interpreter that can execute LLVM bitcode in a managed environment.
  • gu: This tool can be used to install language packs for Python, R, and Ruby, as well as the native-image tool.

我们要做的第一件事是将安装 GraalVM 的路径导出到我们的环境中:

export GRAALVM_HOME=/path/to/graal

另外,建议完成安装,将 GraalVM 的 bin 文件夹添加到您操作系统的 PATH 中。例如,在 Linux 上,我们将执行以下操作:

 export PATH=$PATH:$GRAALVM_HOME

或者,您可以通过设置 JAVA_HOME 环境变量来解析到 GraalVM 安装目录,如下所示:

 export JAVA_HOME=$GRAALVM_HOME
All the preceding environment settings should be added to the script that initializes your shell. For most Linux distributions, this means putting them in the .bashrc file.

设置 PATH 环境变量后,使用 GraalVM 的启动器检查语言版本非常简单:

$ java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-20191008104205.buildslave.jdk8u-src-tar--b07)
OpenJDK 64-Bit GraalVM CE 19.2.1 (build 25.232-b07-jvmci-19.2-b03, mixed mode)

$ node -v
v10.16.3
 
$ lli --version
LLVM (GraalVM CE Native 19.2.1)

属于 GraalVM 中所有语言运行时的可执行文件模拟语言默认运行时的行为。在 PATH 环境变量的开头包含 GraalVM 就足够了,以便使用 GraalVM 运行您的应用程序。

Running a Java application with GraalVM

为了测试您的 GraalVM 环境是否正常工作,我们将添加一个最小的 Java 类并运行它。打开编辑器并创建以下 Main 类:

public class Main {
 public static void main(String[] args) {
 System.out.println("Hello GraalVM!");
 }
}

将此类编译成字节码,然后使用以下命令在 GraalVM 上运行:

$ javac Main.java
$ java Main

这将为我们提供以下输出:

 Hello GraalVM!

Building native images

现在我们已经测试了 Java 字节码的编译和执行,我们将把字节码转换为原生可执行文件,以实现更快的启动和更小的应用程序占用空间。为此,我们需要 native-image 工具,它允许我们将 Java 代码 AOT 编译成独立的可执行文件。我们可以如下安装native-image工具:

${GRAALVM_HOME}/bin/gu install native-image

成功安装后,我们可以针对 我们创建的同一个 HelloWorld Java 类使用 native-image 工具。运行以下命令构建原生镜像:

 $ native-image Main

您将看到以下输出:

Build on Server(pid: 7874, port: 38225)*
[main:7874]    classlist:   1,156.93 ms
[main:7874]        (cap):     859.74 ms
[main:7874]        setup:   1,940.59 ms
[main:7874]   (typeflow):   2,415.87 ms
[main:7874]    (objects):     680.43 ms
[main:7874]   (features):     124.69 ms
[main:7874]     analysis:   3,517.35 ms
[main:7874]     universe:     179.14 ms
[main:7874]      (parse):     413.36 ms
[main:7874]     (inline):     728.98 ms
[main:7874]    (compile):   3,642.72 ms
[main:7874]      compile:   5,219.51 ms
[main:7874]        image:     304.89 ms
[main:7874]        write:      97.09 ms
[main:7874]      [total]:  12,891.94 ms

这会在当前工作目录中构建一个大小仅为 2 MB 的可执行文件,名为 main

$ ls -al main 
-rwxrwxr-x. 1 francesco francesco 2481352 Apr 16 10:06 main

调用它会执行Main类的原生编译代码,如下:

$ ./main
Hello GraalVM!

一旦我们验证了我们安装的 GraalVM 可以正常工作,我们就可以安装一个开发环境,运行本书中包含的示例将需要该环境。

Installing a development environment

随着我们远离单体开发,选择开发环境变得不那么重要了,在单体开发中,通常需要大量插件来构建应用层之间的复杂交互。因此,我们可以选择任何能够本地导入/导出 Maven 或 Gradle 项目的 IDE,以及一套不错的功能来加速我们的代码或重构它。我们将使用 IntelliJ IDEA,我们可以从 https://www.jetbrains .com/idea/.

下载页面(https://www .jetbrains.com/idea/download/),终极版和社区版均可用。我们将使用后者,它可以免费下载。 选择为您的操作系统下载最新的二进制文件。 然后,将其解压缩到您喜欢的文件夹中(例如例如,在您的 Home 文件夹中):

tar xvzf ideaIC-2019.1.tar.gz -C $HOME

接下来,进入安装的bin文件夹,使用以下命令执行:

 ./idea.sh

让我们对开发环境的视觉元素有一个最小的概述。

A brief overview of IntelliJ IDEA

尽管我们不会专注于特定的开发环境来了解 Quarkus,但我们将简要概述构成 IntelliJ IDEA 的视觉元素,以了解您可以更快、更轻松地执行哪些操作。如以下屏幕截图所示,这些是 IntelliJ IDEA 界面的主要元素:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

让我们看一下各个突出显示的部分:

  1. Menu bar: The menu bar includes options we can use to create or import projects and other key actions related to projects, such as code refactoring, builds, run, debug, version-control options, and so on.
  2. Toolbar: The toolbar contains some shortcuts for common execution actions, such as compile, debug, and run. You can also customize it according to your requirements.
  3. Navigation bar: The navigation bar enables navigation between sources within a project. This feature will come in handy as your code base grows.
  4. Tools tab: The tools tab, which can show up on either side of the main window, lets you access key tools such as Maven/Ant builds, databases, and so on.
  1. Project perspective: The project perspective window contains all the elements of your project, such as packages, modules, classes, external libraries, and so on.
  2. Editor window: This is where you edit your code in IntelliJ IDEA using advanced features such as syntax highlighting, smart completion, quick-fix suggestions, and other useful features.

太棒了! 在下一章中,我们将使用 Quarkus 创建一个简单的应用程序,并将其导入 IntelliJ IDEA。

Installing IntelliJ Plugin for Quarkus

在结束本章之前,值得一提的是 IntelliJ IDEA 在其插件市场中包含一个用于引导 Quarkus 应用程序的插件。您可以通过 File |设置 |插件 顶部菜单选项。选择 Plugin 选项后,在市场文本字段中搜索“quarkus”。

找到后,点击 Install 按钮,如下图所示:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

重新启动 IDE 以使更改生效。安装插件后,您可以直接从 IDE 添加新的 Quarkus 项目。这是更新的项目列表的快照:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

项目向导将指导您选择项目的 Maven 坐标以及您希望包含在其中的扩展:

读书笔记《hands-on-cloud-native-applications-with-java-and-quarkus》Quarkus核心概念简介

在驶入未知水域之前,我们将暂停一会儿,简要回顾一下我们在本章中学到的内容。然后,喝杯茶,准备出发!

Summary

在本章中,我们概述了 IT 行业的当前格局。正如我们所了解的,Kubernetes 通过提供一组新的分布式服务和运行时环境来创建跨多个节点的分布式系统,从而为传统的基于语言的构建块添加了一个全新的维度。尽管创建容器化应用程序的核心原则并不严格要求您将单体应用程序分解为单个服务,但这样做在隔离性、可扩展性、团队独立性、监控、弹性和生命周期自动化方面具有明显的优势。

后来,我们通过介绍 Quarkus 讨论了可以本地运行的实际应用程序,这是一个令人惊叹的框架,我们可以在其中创建无服务器的本地应用程序,而不会失去我们作为 Java 开发人员所学的技能。

现在我们已经安装了开始使用 Quarkus 所需的工具,在下一章中,我们将编写我们的第一个示例应用程序。