SmallRye 健康检查
本指南演示了您的 Quarkus 应用程序如何使用 SmallRye Health,它是 MicroProfile Health 规范的一个实现。
SmallRye Health 允许应用程序向外部查看者提供有关其状态的信息,这在云环境中通常很有用,在这些环境中,自动化流程必须能够确定是否应丢弃或重新启动应用程序。
先决条件
要完成本指南,您需要
-
大约 15 分钟
-
一个 IDE
-
已安装 JDK 17+ 并正确配置了
JAVA_HOME
-
Apache Maven 3.9.9
-
如果您想使用它,可以选择 Quarkus CLI
-
如果您想构建本机可执行文件(或者如果您使用本机容器构建,则为 Docker),可以选择安装 Mandrel 或 GraalVM 并进行适当的配置
解决方案
我们建议您按照以下章节中的说明,逐步创建应用程序。但是,您可以直接转到完整的示例。
克隆 Git 存储库:git clone https://github.com/quarkusio/quarkus-quickstarts.git
,或下载 存档。
解决方案位于 microprofile-health-quickstart
目录中。
创建 Maven 项目
首先,我们需要一个新项目。使用以下命令创建一个新项目
对于 Windows 用户
-
如果使用 cmd,(不要使用反斜杠
\
并将所有内容放在同一行上) -
如果使用 Powershell,请将
-D
参数用双引号引起来,例如"-DprojectArtifactId=microprofile-health-quickstart"
此命令会生成一个项目,并导入 smallrye-health
扩展。
如果您已经配置了 Quarkus 项目,则可以通过在项目基本目录中运行以下命令将 smallrye-health
扩展添加到项目中
quarkus extension add smallrye-health
./mvnw quarkus:add-extension -Dextensions='smallrye-health'
./gradlew addExtension --extensions='smallrye-health'
这会将以下内容添加到您的构建文件中
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
implementation("io.quarkus:quarkus-smallrye-health")
运行健康检查
导入 smallrye-health
扩展会直接公开三个 REST 端点
-
/q/health/live
- 应用程序已启动并正在运行。 -
/q/health/ready
- 应用程序已准备好为请求提供服务。 -
/q/health/started
- 应用程序已启动。 -
/q/health
- 累积应用程序中的所有健康检查过程。
要检查 smallrye-health
扩展是否按预期工作
-
使用以下命令启动您的 Quarkus 应用程序
CLIquarkus dev
Maven./mvnw quarkus:dev
Gradle./gradlew --console=plain quarkusDev
-
使用浏览器或
curl https://:8080/q/health/live
访问https://:8080/q/health/live
端点
所有 health
REST 端点都返回一个简单的 JSON 对象,其中包含两个字段
-
status
— 所有健康检查过程的总体结果 -
checks
— 单个检查的数组
健康检查的总体 status
计算为所有声明的健康检查过程的逻辑 AND。由于我们尚未指定任何健康检查过程,因此 checks
数组为空,因此让我们定义一些。
管理界面
默认情况下,健康检查在主 HTTP 服务器上公开。您可以通过启用管理界面并设置 |
创建您的第一个健康检查
在本节中,我们将创建我们的第一个简单的健康检查过程。
创建 org.acme.microprofile.health.SimpleHealthCheck
类
package org.acme.microprofile.health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Liveness;
import jakarta.enterprise.context.ApplicationScoped;
@Liveness
@ApplicationScoped (1) (2)
public class SimpleHealthCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("Simple health check");
}
}
1 | 建议使用 @ApplicationScoped 或 @Singleton 作用域注释健康检查类,以便将单个 bean 实例用于所有健康检查请求。 |
2 | 如果使用其中一个健康检查注释注释的 bean 类未声明任何作用域,则会自动使用 @Singleton 作用域。 |
如您所见,健康检查过程被定义为 CDI bean,这些 bean 实现 HealthCheck
接口,并使用健康检查限定符之一进行注释,例如
-
@Liveness
- 可在/q/health/live
访问的活跃性检查 -
@Readiness
- 可在/q/health/ready
访问的就绪性检查
HealthCheck
是一个函数式接口,它的单个方法 call
返回一个 HealthCheckResponse
对象,该对象可以通过示例中显示的 fluent builder API 轻松构建。
由于我们已在开发模式下启动了 Quarkus 应用程序,只需通过刷新浏览器窗口或使用 curl https://:8080/q/health/live
重复请求 https://:8080/q/health/live
。因为我们将健康检查定义为活跃性过程(使用 @Liveness
限定符),所以新的健康检查过程现在存在于 checks
数组中。
恭喜!您已经创建了您的第一个 Quarkus 健康检查过程。让我们继续探索 SmallRye Health 还可以做什么。
添加就绪性健康检查过程
在上一节中,我们创建了一个简单的活跃性健康检查过程,用于说明我们的应用程序是否正在运行。在本节中,我们将创建一个就绪性健康检查,该检查能够说明我们的应用程序是否能够处理请求。
我们将创建另一个健康检查过程,该过程模拟与外部服务提供商(例如数据库)的连接。对于初学者,我们将始终返回响应,指示应用程序已准备好。
创建 org.acme.microprofile.health.DatabaseConnectionHealthCheck
类
package org.acme.microprofile.health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Readiness;
import jakarta.enterprise.context.ApplicationScoped;
@Readiness
@ApplicationScoped
public class DatabaseConnectionHealthCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("Database connection health check");
}
}
如果您现在重新运行 https://:8080/q/health/live
上的健康检查,则 checks
数组将仅包含先前定义的 SimpleHealthCheck
,因为它是使用 @Liveness
限定符定义的唯一检查。但是,如果您访问 https://:8080/q/health/ready
(在浏览器中或使用 curl https://:8080/q/health/ready
),您将只看到 Database connection health check
,因为它是使用 @Readiness
限定符定义的唯一健康检查作为就绪性健康检查过程。
如果您访问 https://:8080/q/health ,您将获得两个检查。 |
MicroProfile Health 规范中详细介绍了在哪些情况下应使用哪些健康检查过程的更多信息。通常,活跃性过程确定是否应重新启动应用程序,而就绪性过程确定通过请求联系应用程序是否有意义。
添加启动健康检查过程
第三种也是最后一种类型的健康检查过程是启动。启动过程被定义为慢速启动容器的一个选项(Quarkus 中不需要),用于延迟活跃性探测的调用,活跃性探测将在启动第一次响应 UP 后接管。启动健康检查使用 @Startup
限定符定义。
请确保您导入 microprofile org.eclipse.microprofile.health.Startup 注释,因为与 io.quarkus.runtime.Startup 存在不幸的冲突。 |
创建 org.acme.microprofile.health.StartupHealthCheck
类
package org.acme.microprofile.health;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.Startup;
import jakarta.enterprise.context.ApplicationScoped;
@Startup
@ApplicationScoped
public class StartupHealthCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.up("Startup health check");
}
}
启动健康检查将在 https://:8080/q/health/started
或与其他健康检查过程一起在 https://:8080/q/health
上可用。
负面健康检查过程
在本节中,我们将扩展我们的 Database connection health check
,并可以选择声明我们的应用程序未准备好处理请求,因为无法建立底层数据库连接。为简单起见,我们仅通过配置属性确定是否可以访问数据库。
更新 org.acme.microprofile.health.DatabaseConnectionHealthCheck
类
package org.acme.microprofile.health;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import org.eclipse.microprofile.health.HealthCheckResponseBuilder;
import org.eclipse.microprofile.health.Readiness;
import jakarta.enterprise.context.ApplicationScoped;
@Readiness
@ApplicationScoped
public class DatabaseConnectionHealthCheck implements HealthCheck {
@ConfigProperty(name = "database.up", defaultValue = "false")
private boolean databaseUp;
@Override
public HealthCheckResponse call() {
HealthCheckResponseBuilder responseBuilder = HealthCheckResponse.named("Database connection health check");
try {
simulateDatabaseConnectionVerification();
responseBuilder.up();
} catch (IllegalStateException e) {
// cannot access the database
responseBuilder.down();
}
return responseBuilder.build();
}
private void simulateDatabaseConnectionVerification() {
if (!databaseUp) {
throw new IllegalStateException("Cannot contact database");
}
}
}
到目前为止,我们使用了一种简化的方法,通过 HealthCheckResponse#up(String) (还有 HealthCheckResponse#down(String) )构建 HealthCheckResponse ,这将直接构建响应对象。从现在开始,我们将利用 HealthCheckResponseBuilder 类提供的完整构建器功能。 |
如果您现在重新运行就绪性健康检查(在 https://:8080/q/health/ready
),则总体 status
应为 DOWN。您还可以在 https://:8080/q/health/live
检查活跃性检查,这将返回总体 status
UP,因为它不受就绪性检查的影响。
由于我们不应将此应用程序的就绪性检查保持在 DOWN 状态,并且因为我们正在开发模式下运行 Quarkus,您可以在 src/main/resources/application.properties
中添加 database.up=true
并再次重新运行就绪性健康检查 — 它应该再次启动。
将用户特定数据添加到健康检查响应
在前面的章节中,我们了解了如何创建仅具有最小属性(即健康检查名称及其状态(UP 或 DOWN))的简单健康检查。但是,MicroProfile Health 规范还提供了一种方式,供应用程序以键值对的形式向使用者发送任意数据。这可以通过使用健康检查响应构建器 API 的 withData(key, value)
方法来完成。
让我们创建一个新的健康检查过程 org.acme.microprofile.health.DataHealthCheck
package org.acme.microprofile.health;
import org.eclipse.microprofile.health.Liveness;
import org.eclipse.microprofile.health.HealthCheck;
import org.eclipse.microprofile.health.HealthCheckResponse;
import jakarta.enterprise.context.ApplicationScoped;
@Liveness
@ApplicationScoped
public class DataHealthCheck implements HealthCheck {
@Override
public HealthCheckResponse call() {
return HealthCheckResponse.named("Health check with data")
.up()
.withData("foo", "fooValue")
.withData("bar", "barValue")
.build();
}
}
如果您通过访问 /q/health/live
端点重新运行活跃性健康检查过程,您可以看到新的健康检查 Health check with data
存在于 checks
数组中。此检查包含一个名为 data
的新属性,它是由我们在健康检查过程中定义的属性组成的 JSON 对象。
此功能在故障情况下特别有用,您可以在健康检查响应中传递错误。
try {
simulateDatabaseConnectionVerification();
responseBuilder.up();
} catch (IllegalStateException e) {
// cannot access the database
responseBuilder.down()
.withData("error", e.getMessage()); // pass the exception message
}
将上下文传播到健康检查调用中
出于性能原因,上下文(例如 CDI 或安全上下文)不会传播到每个健康检查调用中。但是,如果您需要启用此功能,可以设置配置属性 quarkus.smallrye-health.context-propagation=true
以允许上下文传播到每个健康检查调用中。
响应式健康检查
MicroProfile Health 当前不支持返回响应式类型,但 SmallRye Health 支持。
如果您想提供响应式健康检查,您可以实现 io.smallrye.health.api.AsyncHealthCheck
接口,而不是 org.eclipse.microprofile.health.HealthCheck
接口。io.smallrye.health.api.AsyncHealthCheck
接口允许您返回 Uni<HealthCheckResponse>
。
以下示例显示了响应式活跃性检查
import io.smallrye.health.api.AsyncHealthCheck;
import org.eclipse.microprofile.health.Liveness;
import org.eclipse.microprofile.health.HealthCheckResponse;
import jakarta.enterprise.context.ApplicationScoped;
@Liveness
@ApplicationScoped
public class LivenessAsync implements AsyncHealthCheck {
@Override
public Uni<HealthCheckResponse> call() {
return Uni.createFrom().item(HealthCheckResponse.up("liveness-reactive"))
.onItem().delayIt().by(Duration.ofMillis(10));
}
}
健康状态更改观察者
如果您需要对应用程序的健康状态更改做出反应,则 Smallrye Health 扩展提供了一个 CDI 事件,可以通知您有关各个健康状态更改。
要观察健康状态更改,您可以使用标准 CDI 观察机制观察 io.smallrye.health.api.event.HealthStatusChangeEvent
。由于我们不能保证观察者方法始终在工作线程上运行(这意味着它可以在事件循环线程上运行),因此建议您永远不要在观察者方法中阻塞。
import io.smallrye.health.api.event.HealthStatusChangeEvent;
@ApplicationScoped
public class HealthObserver {
public void observeHealthChange(@Observes @Default HealthStatusChangeEvent event) {
...
}
public void observeReadinessChange(@Observes @Readiness HealthStatusChangeEvent event) {
...
}
public void observeLivenessChange(@Observes @Liveness HealthStatusChangeEvent event) {
...
}
}
扩展健康检查
某些扩展可能会提供默认健康检查,包括扩展会自动注册其健康检查。
例如,用于管理 Quarkus 数据源的 quarkus-agroal
会自动注册一个就绪性健康检查,该检查将验证每个数据源:数据源健康检查。
您可以通过属性 quarkus.health.extensions.enabled
禁用扩展健康检查,因此不会自动注册任何健康检查。
健康检查 UI
实验性 - 未包含在 MicroProfile 规范中 |
health-ui
允许您在 Web GUI 中查看您的健康检查。
Quarkus smallrye-health
扩展附带 health-ui
,并且默认情况下在开发和测试模式下启用它,但也可以显式配置为生产模式。
可以从 https://:8080/q/health-ui/ 访问 health-ui
。
管理界面
默认情况下,健康检查在主 HTTP 服务器上公开。您可以通过在应用程序配置中设置 quarkus.management.enabled=true
将它们公开在单独的网络接口和端口上。请注意,此属性是一个构建时属性。该值无法在运行时被覆盖。
如果您启用管理界面而不自定义管理网络接口和端口,则健康检查将在以下位置公开:http://0.0.0.0:9000/q/health
。您可以使用 quarkus.smallrye-health.root-path
属性配置路径(先前 URL 中的 health
段)。
有关更多信息,请参阅管理界面参考。
结论
SmallRye Health 为您的应用程序提供了一种分发有关其健康状态的信息的方式,以说明它是否能够正常运行。活跃性检查用于判断是否应重新启动应用程序,而就绪性检查用于判断应用程序是否能够处理请求。
要在 Quarkus 中启用 SmallRye Health 功能,只需
-
使用
quarkus-maven-plugin
将smallrye-health
Quarkus 扩展添加到您的项目中CLIquarkus extension add smallrye-health
Maven./mvnw quarkus:add-extension -Dextensions='smallrye-health'
Gradle./gradlew addExtension --extensions='smallrye-health'
-
或者只需添加以下 Maven 依赖项
pom.xml<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-smallrye-health</artifactId> </dependency>
build.gradleimplementation("io.quarkus:quarkus-smallrye-health")
配置参考
构建时固定的配置属性 - 所有其他配置属性都可以在运行时覆盖
配置属性 |
类型 |
默认 |
---|---|---|
激活或禁用此扩展。禁用此扩展意味着不公开任何与健康相关的信息。 环境变量: 显示更多 |
布尔值 |
|
是否应启用扩展发布的健康检查。 环境变量: 显示更多 |
布尔值 |
|
是否在生成的 OpenAPI 文档中包含活跃性和就绪性健康端点 环境变量: 显示更多 |
布尔值 |
|
健康检查端点的根路径。默认情况下,此值将被解析为相对于 环境变量: 显示更多 |
字符串 |
|
活跃性健康检查端点的相对路径。默认情况下,此值将被解析为相对于 环境变量: 显示更多 |
字符串 |
|
就绪性健康检查端点的相对路径。默认情况下,此值将被解析为相对于 环境变量: 显示更多 |
字符串 |
|
健康组端点的相对路径。默认情况下,此值将被解析为相对于 环境变量: 显示更多 |
字符串 |
|
健康状况良好检查端点的相对路径。默认情况下,此值将被解析为相对于 环境变量: 显示更多 |
字符串 |
|
启动健康检查端点的相对路径。默认情况下,此值将被解析为相对于 环境变量: 显示更多 |
字符串 |
|
是否应将上下文传播到每个健康检查调用。 环境变量: 显示更多 |
布尔值 |
|
可以创建的最大健康组数。 环境变量: 显示更多 |
整数 |
|
在健康检查上未定义其他健康组时使用的默认健康组的名称。 环境变量: 显示更多 |
字符串 |
|
如果启用了管理界面,则健康端点和 UI 将在管理界面下发布。这允许您通过将该值设置为 false 来将健康检查排除在管理之外 环境变量: 显示更多 |
布尔值 |
|
指定报告的 DOWN 响应是否应与 RFC 9457 - HTTP API 的问题详细信息对齐。 环境变量: 显示更多 |
布尔值 |
|
是否应启用健康检查 UI。默认情况下,如果包含健康检查 UI(请参阅 环境变量: 显示更多 |
布尔值 |
|
要包含在结果 JSON 对象中的其他顶级属性。 环境变量: 显示更多 |
Map<String,String> |
|
是否应启用 HealthCheck。 环境变量: 显示更多 |
布尔值 |
|
类型 |
默认 |
|
健康检查 UI 可用的路径。不允许使用值 环境变量: 显示更多 |
字符串 |
|
始终包含 UI。默认情况下,这仅包含在开发和测试中。将此设置为 true 还将在生产环境中包含 UI 环境变量: 显示更多 |
布尔值 |
|