写点什么

【Quarkus 技术系列】「云原生架构体系」配置参考指南相关的功能机制配置介绍分析

作者:浩宇天尚
  • 2021 年 11 月 16 日
  • 本文字数:5452 字

    阅读完需:约 18 分钟

【Quarkus技术系列】「云原生架构体系」配置参考指南相关的功能机制配置介绍分析

回顾 Quarkus 介绍

Quarkus 的概念定义

Quarkus 是一个为 Java 虚拟机(JVM)和原生编译而设计的全堆栈 Kubernetes 原生 Java 框架,用于专门针对容器优化 Java,并使其成为无服务器、云和 Kubernetes 环境的高效平台。

Quarkus 与框架整合

Quarkus 可与常用 Java 标准、框架和库协同工作,例如:Eclipse MicroProfile、Spring、Apache Kafka、RESTEasy (JAX-RS)、Hibernate ORM (JPA)、Spring、Infinispan、Camel 等。

Quarkus 的依赖注入

Quarkus 的依赖注入解决方案基于 CDI(上下文和依赖注入),且包含一个扩展框架来扩展功能并将其配置、引导并集成到您的应用中。添加扩展就像添加依赖项一样容易;或者,您可以使用 Quarkus 工具。

Quarkus 多语言化

  • GraalVM(一种通用虚拟机,用于运行以多种语言(包括 Java 和 JavaScript)编写的应用)提供正确信息,以便对应用进行原生编译。

  • 惊人的快速启动时间,极低的 RSS 内存(不仅是堆大小!)在容器编排平台(如 Kubernetes)中提供了近乎即时的向上扩展和高密度的内存利用率

专为开发人员而设计

Quarkus 的设计从一开始就立足于简单易用,其功能几乎不需要配置即可正常使用。


开发人员可以为其应用选择所需的 Java 框架,而这些应用可以在 JVM 模式下运行,也可以在原生模式下进行编译和运行。


可为开发人员带来最佳的欢乐:

统一配置
  • 零配置,瞬间重载实时重载

  • 简化了 80%常用用法的代码,灵活了 20%的用法

  • 无需麻烦的本机可执行文件生成

容器优先
  • 无论是将应用托管在公共云上还是内部托管的 Kubernetes 集群中,快速启动和低内存消耗等特性对于降低总体主机成本来说都至关重要。

  • Quarkus 的开发遵从了容器优先的原则,这意味着它已通过以下方式针对降低内存使用和加快启动时间进行了优化

  • 鼎力支持 Graal/SubstrateVM

  • 构建时元数据处理

  • 减少反射的使用

  • 本机映像预启动


Quarkus 构建的应用其内存消耗只有传统 Java 的 1/10,而且启动时间更快(快了 300 倍),这些都大大降低了云资源的成本。


云原生

在 Kubernetes 等环境中采用 12 要素原则。

统一命令式与反应式

在设计上,Quarkus 能够在开发应用时无缝地结合熟悉的命令式代码和非阻塞、响应式样式。


这对于习惯使用命令式模型而不想切换风格的 Java 开发人员以及使用云原生/响应式方法的开发人员都非常有用。


基于标准

Quarkus 通过利用您喜欢和使用的五十多种最佳库的不断增长的列表,提供了一个内聚的,易于使用的,全栈的框架。所有都连接在标准主干上


Quarkus 开发模型可以适应您正在开发的任何应用


对于在新的无服务器架构、微服务、容器、Kubernetes、功能即服务(FaaS)和云环境中运行 Java 而言,Quarkus 堪称是一个有效的解决方案,因为在创建它时就充分考虑了所有这些因素。

使用 DI 注入

  • Quarkus 中的依赖注入基于 ArC,ArC 是为 Quarkus 架构量身定制的基于 CDI 的依赖注入解决方案。如果您不熟悉 CDI,建议您阅读 CDI 简介指南。

  • Quarkus 仅实现 CDI 功能的一个子集,并具有非标准功能和特定的 APIS,您可以在 Contexts and Dependency Injection 指南中了解有关它的更多信息。

  • ArC 作为的依赖项,quarkus-resteasy 因此您已经很方便了。

配置参考指南

Quarkus 应用程序和 Quarkus 本身(核心和扩展)都通过相同的机制进行配置,该机制利用 SmallRye Config API 和 MicroProfile Config 规范的实现。Quarkus 本身提供了一些附加功能。

配置源

默认情况下,Quarkus 从多个来源(优先级递减)中读取配置属性:


  • 系统属性

  • 环境变量

  • 名为文件.env 放置在当前工作目录中

  • application.properties 文件放在 $PWD/config/目录中

  • 应用程序配置文件,即 src/main/resources/application.properties

系统属性

运行 jar:
java -Dquarkus.datasource.password=youshallnotpass -jar target/quarkus-app/quarkus-run.jar
复制代码
native 执行文件:
./target/myapp-runner -Dquarkus.datasource.password=youshallnotpass
复制代码

环境变量

运行 jar:
export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ; java -jar target/quarkus-app/quarkus-run.jar
复制代码
native 可执行文件:
export QUARKUS_DATASOURCE_PASSWORD=youshallnotpass ;./target/myapp-runner
复制代码

文件名为.env 放置在当前工作目录中

示例.env 文件


QUARKUS_DATASOURCE_PASSWORD=youshallnotpassQUARKUS_DATASOURCE_PASSWORD使用与环境变量相同的规则来转换名称。
复制代码


对于开发人员模式,此文件可以放在项目的根目录中,但建议不要将其检入版本控制。


没有定义的配置文件的环境变量.env 文件将覆盖其所有相关的配置文件中 application.properties,例如,%test.application.value 被覆盖 APPLICATION_VALUE 的.env 文件。

application.properties 文件放置在 $PWD/config/

  • 将 application.properties 文件放置在名为 config 的目录中,该目录位于应用程序运行的目录中,该文件中定义的所有运行时属性都将覆盖默认配置。

  • 此外,添加到该文件中的任何不属于原始 application.properties 文件的 运行时属性也将被考虑在内。对于运行程序 jar 和本机可执行文件,其工作方式相同。

  • 该 config/application.properties 功能在开发模式下也可用。

  • 要使用它,config/application.properties 需要放置在构建工具的输出目录中。但是请记住,从构建工具进行的任何清理操作(例如 mvn clean 或)gradle clean 也会删除该 config 目录。

应用程序配置文件

位于中的主要应用程序配置文件 src/main/resources/application.properties。

application.properties 文件
greeting.message=hello quarkus.http.port=9090 
复制代码


Quarkus 支持在文件中使用属性表达式 application.properties。

将配置文件嵌入到依赖项中
  • 可以通过向 META-INF/microprofile-config.properties 配置文件中添加一个配置文件来将配置文件嵌入其中(这是 MicroProfile Config 的标准功能)。

  • 当将此依赖项添加到应用程序时,其配置属性将被合并。

  • 可以覆盖优先于它的属性来自它的属性 application.properties。

注入配置属性

Quarkus 使用 MicroProfile Config 注释在应用程序中注入配置属性。


@ConfigProperty(name = "greeting.message") String message;
复制代码


可以使用@Inject @ConfigProperty 或 @ConfigProperty。对于使用 @Inject 注释的成员,注释不是必需的 @ConfigProperty。此行为不同于 MicroProfile Config。


如果应用程序尝试注入未设置的配置属性,则会引发错误,从而使您可以快速了解配置何时完成。

@ConfigProperty 例子
@ConfigProperty(name = "greeting.message") String message;
@ConfigProperty(name = "greeting.suffix", defaultValue="!") String suffix;
@ConfigProperty(name = "greeting.name")Optional<String> name;
复制代码


如果您不提供此属性的值,则应用程序启动将失败


javax.enterprise.inject.spi.DeploymentException: No config value of type [class java.lang.String] exists for: greeting.message。
复制代码


如果配置未提供的值,则会注入默认值 greeting.suffix。


此属性是可选的-Optional 如果配置未提供的值,则会注入一个空值 greeting.name。

以编程方式访问配置

可以通过编程方式访问配置。实现动态查找或从既不是 CDI bean 也不是 JAX-RS 资源的类中检索配置的值可能很方便。


可以使用以下方式以编程方式访问配置


org.eclipse.microprofile.config.ConfigProvider.getConfig():
String databaseName = ConfigProvider.getConfig().getValue("database.name", String.class);Optional<String> maybeDatabaseName = ConfigProvider.getConfig().getOptionalValue("database.name", String.class);
复制代码

使用 @ConfigProperties

作为以上一示例中所示的方式注入多个相关配置值的替代方法,用户还可以使用 @io.quarkus.arc.config.ConfigProperties 注释将这些属性组合在一起。


对于上面的 Greeting 属性,GreetingConfiguration 可以这样创建一个类:


@ConfigProperties(prefix = "greeting") public class GreetingConfiguration {
private String message; private String suffix = "!"; private Optional<String> name;
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public String getSuffix() { return suffix; }
public void setSuffix(String suffix) { this.suffix = suffix; }
public Optional<String> getName() { return name; }
public void setName(Optional<String> name) { this.name = name; }}
复制代码


然后可以 GreetingResource 使用 @Inject 类似的 CDI 注释将此类注入到,如下所示:


@InjectGreetingConfiguration greetingConfiguration;
复制代码


Quarkus 提供的另一种替代样式是 GreetingConfiguration 像这样创建接口:


package org.acme.config;
import io.quarkus.arc.config.ConfigProperties;import org.eclipse.microprofile.config.inject.ConfigProperty;import java.util.Optional;
@ConfigProperties(prefix = "greeting")public interface GreetingConfiguration {
@ConfigProperty(name = "message") String message();
@ConfigProperty(defaultValue = "!") String getSuffix();
Optional<String> getName(); }
复制代码


在 @ConfigProperties 类或接口上使用时,如果未提供其字段之一的值,则应用程序启动将失败,并且将 javax.enterprise.inject.spi.DeploymentException 显示指示缺少值的信息。这不适用于 Optional 字段和具有默认值的字段。

有关 @ConfigProperties 的其他说明

当使用带有类注释的常规类时,@ConfigProperties 不一定必须声明 getter 和 setter。具有简单的公共非最终字段也是有效的。


此外,配置类支持嵌套对象配置。假设需要有一个额外的问候语配置层,名称 content 将包含一些字段。可以这样实现:


@ConfigProperties(prefix = "greeting")public class GreetingConfiguration {
public String message; public String suffix = "!"; public Optional<String> name; public ContentConfig content;
public static class ContentConfig { public Integer prizeAmount; public List<String> recipients; }}
复制代码


字段名称(不是类名称)将确定绑定到对象的属性的名称。


设置属性将以正常方式进行,例如,application.properties 可能具有:


greeting.message = hellogreeting.name = quarkusgreeting.content.prize-amount=10greeting.content.recipients=Jane,John
复制代码


此外,@ConfigProperties 可以使用 Bean Validation 批注来批注使用批注的类,类似于以下示例:


@ConfigProperties(prefix = "greeting")public class GreetingConfiguration {
@Size(min = 20) public String message; public String suffix = "!";
}
复制代码


为了使验证生效,quarkus-hibernate-validator 需要提供扩展名


如果使用给定的配置验证失败,则应用程序将无法启动,并在日志中指示相应的验证错误。


如果接口带有注释 @ConfigProperties,则允许该接口扩展其他接口,并且使用整个接口层次结构中的方法来绑定属性。

使用具有不同前缀的相同 ConfigProperty

Quarkus 还支持使用注解 @ConfigProperties 为每个注入点使用带有不同前缀的同一对象 io.quarkus.arc.config.@ConfigPrefix。举例来说,前缀和前缀 GreetingConfiguration 都需要使用以上代码。在这种情况下,代码如下所示:greetingother


GreetingConfiguration.java
@ConfigProperties(prefix = "greeting")public class GreetingConfiguration {
@Size(min = 20) public String message; public String suffix = "!";
}SomeBean.java
@ApplicationScopedpublic class SomeBean {
@Inject GreetingConfiguration greetingConfiguration;
@ConfigPrefix("other") GreetingConfiguration otherConfiguration;
}
复制代码

使用对象列表

在某些情况下,可能有必要支持利用对象列表的复杂配置结构,如以下示例所示:


ComplexConfiguration.java
@ConfigProperties(prefix = "complex")public class ComplexConfiguration { public String name; public String user; public String password; public List<Nested> inputs; public List<Nested> outputs; public static class Nested { public String user; public String password; }}
复制代码


仅当将 YAML 配置与 quarkus-config-yaml 扩展一起使用时,才对此类用例提供支持。相应的示例 YAML 配置可以是:


application.yaml


complex:  name: defaultName  user: defaultUser  password: defaultPassword  inputs:    - user: user      password: secret    - user: otheruser      password: secret2  outputs:    - user: someuser      password: asecret    - user: someotheruser      password: anothersecret
复制代码


这种配置的局限性在于用作列表的通用类型的类型必须是类而不是接口

配置配置文件

Quarkus 支持配置配置文件的概念。这些允许您在同一文件中具有多个配置,并通过配置文件名称在它们之间进行选择。


语法为 %{profile}.config.key=value。例如,如果我有以下内容:


quarkus.http.port=9090%dev.quarkus.http.port=8181
复制代码


除非 dev 配置文件处于活动状态,否则 Quarkus HTTP 端口将为 9090 ,在这种情况下,它将为 8181。


要在.env 文件中使用配置文件,可以遵循一种_{PROFILE}_CONFIG_KEY=value 模式。.env 文件中上述示例的等效内容为:


QUARKUS_HTTP_PORT=9090_DEV_QUARKUS_HTTP_PORT=8181
复制代码


发布于: 5 小时前阅读数: 10
用户头像

浩宇天尚

关注

🏆 InfoQ写作平台-签约作者 🏆 2020.03.25 加入

【个人简介】酷爱计算机技术、醉心开发编程、喜爱健身运动、热衷悬疑推理的”极客狂人“ 【技术格言】任何足够先进的技术都与魔法无异 【技术范畴】Java领域、Spring生态、MySQL专项、APM专题及微服务/分布式体系等

评论

发布
暂无评论
【Quarkus技术系列】「云原生架构体系」配置参考指南相关的功能机制配置介绍分析