Quarkus如何使用构建时间更快地启动应用程序
#云 #java #quarkus #optimization

在此主题中,我们将尝试揭示Quarkus如何增强应用程序的基础知识。我们将介绍构建过程的工作原理,所产生的工件的结构以及如何启动。

什么是quarkus

Quarkus是Java(主要)和Kotlin的框架,专注于云开发。

Quarkus的好处是什么

  • 快速启动
  • 低内存消耗
  • 构建时间DI分辨率

Quarkus如何构建应用程序

在构建时间(也称为部署时间),Quarkus完成了大部分工作。让我们建立Quarkus如何构建我们的应用程序的基础。

Quarkus应用程序构建流

一旦整理了所有应用程序类,就开始构建Quarkus。在引导过程中,它为构建做准备,例如解决所有应用程序依赖性。接下来,Quarkus执行部署(构建)并产生工件。让我们仔细看看与Quarkus有关的每个步骤。

Quarkus application build flow (JVM mode)

引导阶段

在运行构建Quarkus之前:

  • 解决应用程序依赖性。
  • 构建链。
  • 将初始构建物品生产到构建链中。

核心构建组件

构建过程由两个基本块构建步骤和构建项目组成。

构建项目

它们可以是:

  • 初始和非初始
  • 简单而多

初始构建项目

最初的构建项目是创建并通过Quarkus传递给构建链的,无法通过构建步骤产生。
例如,LaunchModeBuildItem表示发射类型,例如生产,开发或测试。

简单的构建项目

只能在一个实例中产生(只有一个构建步骤
例如,CombinedIndexBuildItem包含索引,这些索引是由包含某个标记文件的应用程序类和依赖项构建的。

多构建项目

可以通过任何数量的构建步骤
产生任何时间 例如,AdditionalBeanBuildItem是通过扩展而产生的,以动态指定bean。

建立步骤

  • @BuildStep注释的方法。
  • 消费构建项目。
  • 通过从方法返回值或使用BuildProducer<BuildItem>来产生构建项目
  • 可以在应用程序启动时记录和调用。

构建步骤记录

构建步骤录制过程的工作如下:

  1. 使用InvocationHandler创建了用于在方法中传递的录音机的代理
  2. 代理记录所有调用信息。
  3. 也为所有返回的值创建了代理。
  4. 在应用程序启动时要调用的字节数是根据代理收集的信息记录的。
  5. 记录为StaticBytecodeRecorderBuildItemMainBytecodeRecorderBuildItem的字节码,并在生成跑步类的MainClassBuildStep中收集。

InvocationHandler虚拟实现:

new InvocationHandler() {   
  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // do something on method invocation
  }
}

(简化)构建过程

构建链模型

所得的构建链可以表示为方向的图形,并用构建项目并将步骤构建为节点。 Quarkus确定哪个构建步骤并不取决于任何其他构建步骤并开始执行。完成后,它在依赖的构建步骤下沿着计数器计数;如果计数器等于0,则它们开始执行。所有执行都是并行完成的。

构建阶段

Pre DI build phase
该方案说明了Quarkus是如何收集依赖注入(DI)的Bean Archives的。该过程首先收集所有档案,无论它们是否含有豆类。接下来,Quarkus从收集的档案中选择Bean档案。

最初,收集所有应用程序类。如果使用多模块应用程序,则在此步骤中仅索引主应用模块中的类,而其他类别则将其视为依赖项。

接下来,ApplicationArchiveBuildStep处理所有应用程序依赖性。如果依赖项符合以下标准之一,则将索引索引:

  • 依赖关系包含指定的标记文件之一,例如META-INF/jandex.idxMETA-INF/beans.xml。可以使用AdditionalApplicationArchiveMarkerBuildItem指定其他标记文件
  • 依赖性包含在生产的IndexDependencyBuildItem
  • 依赖项包含在最初的AdditionalApplicationArchiveBuildItem构建项目之一中,该项目无法由用户生成。

quarkus索引

中指定的所有类

这些档案合并到CombinedIndexBuildItem中,由BeanArchiveProcessor

消耗

然后BeanArchiveProcessor创建Bean Archives索引。如果档案符合以下标准之一,则将其视为豆类档案。

  • 存档包含META-INF/beans.xml
  • 存档至少包含一个带有bean定义注释的类,例如@ApplicationScoped
  • 档案中指定为kude22中的bean存档

打击

在构建时间,Quarkus执行以下任务:

  • 解决所有注射点。
  • 生成豆子的静态代理,以避免反射。
  • 生成字节码在应用程序启动时设置DI。

创建工件阶段

JarResultBuildStep中产生的结果伪像。 Quarkus具有几种人工制品格式。对于JVM默认值和建议是 fast-jar 。它遵循结构。

Build a structure

Quarkus如何开始申请

Quarkus提供了几种启动模式,但在这里我们只专注于生产模式。

要在生产模式下启动应用程序,请启动target/quarkus-app/quarkus-run.jar jar。 QuarkusEntrypoint主类将从lib/boot/

加载

下一步是让QuarkusEntryPoint读取quarkus-application.dat文件,从中创建了Quarkus应用程序的类加载程序RunnerClassLoader。使用quarkus-application.dat的信息,RunnerClassLoader将尝试从父类加载程序(JVM类加载程序)或索引罐中加载类,该类别比JVM类加载程序快。

然后,生成的ApplicationImpl运行,其中静态块包含静态记录,并且起始方法包含运行时记录。看起来像这样:

// $FF: synthetic class
public class ApplicationImpl extends Application {
  static Logger LOG;
  public static StartupContext STARTUP_CONTEXT;

  public ApplicationImpl() {
    super(false);
  }

  static {
  // invoke static recordings
  }

  protected final void doStart(String[] var1) {
    // invoke runtime recordings
  }

  protected final void doStop() {
    STARTUP_CONTEXT.close();
  }

  public String getName() {
    return "simple-app";
  }
}

概括

我们涵盖了类索引,依赖注入的构建时间准备,人工制品结构和应用启动。尽管还有其他重要主题,例如本机可执行创建,依赖项注入的更高级概述以及服务器实现,但最好单独解决它们。