健康检查

健康检查

健康检查用于确保你的应用程序在生产环境中运行时处于健康状态。这可能包括监控服务器上的可用磁盘空间应用程序消耗的内存测试数据库连接

AdonisJS 提供了一些内置的 health checks,以及创建和注册 custom health checks 的能力。

配置健康检查

你可以通过执行以下命令在应用程序中配置健康检查。该命令将创建一个 start/health.ts 文件,并为内存使用已用磁盘空间配置健康检查。你可以随意修改此文件,并添加或删除其他健康检查。

在使用以下命令之前,请确保已安装 @adonisjs/core@6.12.1

node ace configure health_checks
start/health.ts
import { HealthChecks, DiskSpaceCheck, MemoryHeapCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
])

暴露端点

执行健康检查的一种常见方法是暴露一个 HTTP 端点,外部监控服务可以通过该端点来收集健康检查结果。

因此,让我们在 start/routes.ts 文件中定义一个路由,并将 HealthChecksController 绑定到该路由。health_checks_controller.ts 文件在初始设置期间创建,并位于 app/controllers 目录中。

start/routes.ts
import router from '@adonisjs/core/services/router'
const HealthChecksController = () => import('#controllers/health_checks_controller')
router.get('/health', [HealthChecksController])

示例报告

healthChecks.run 方法将执行所有检查,并返回一个详细的 report as a JSON object。报告具有以下属性:

{
"isHealthy": true,
"status": "warning",
"finishedAt": "2024-06-20T07:09:35.275Z",
"debugInfo": {
"pid": 16250,
"ppid": 16051,
"platform": "darwin",
"uptime": 16.271809083,
"version": "v21.7.3"
},
"checks": [
{
"name": "Disk space check",
"isCached": false,
"message": "Disk usage is 76%, which is above the threshold of 75%",
"status": "warning",
"finishedAt": "2024-06-20T07:09:35.275Z",
"meta": {
"sizeInPercentage": {
"used": 76,
"failureThreshold": 80,
"warningThreshold": 75
}
}
},
{
"name": "Memory heap check",
"isCached": false,
"message": "Heap usage is under defined thresholds",
"status": "ok",
"finishedAt": "2024-06-20T07:09:35.265Z",
"meta": {
"memoryInBytes": {
"used": 41821592,
"failureThreshold": 314572800,
"warningThreshold": 262144000
}
}
}
]
}

isHealthy

一个布尔值,用于指示所有检查是否通过。如果有一个或多个检查失败,该值将设置为 false

status

执行所有检查后的报告状态。它将是以下状态之一。

  • ok:所有检查均成功通过。
  • warning:一个或多个检查报告了警告。
  • error:一个或多个检查失败。

finishedAt

测试完成的日期和时间。

checks

包含所有执行检查的详细报告的对象数组。

debugInfo

调试信息可用于识别进程及其运行时长。它包括以下属性。

  • pid:进程 ID。
  • ppid:管理你的 AdonisJS 应用程序进程的父进程 ID。
  • platform:应用程序运行的平台。
  • uptime:应用程序运行的时长(以秒为单位)。
  • version:Node.js 版本。

保护端点

你可以使用身份验证中间件或创建自定义中间件来检查请求头中的特定 API 密钥,从而保护 /health 端点免受公共访问。例如:

import router from '@adonisjs/core/services/router'
const HealthChecksController = () => import('#controllers/health_checks_controller')
router
.get('/health', [HealthChecksController])
.use(({ request, response }, next) => {
if (request.header('x-monitoring-secret') === 'some_secret_value') {
return next()
}
response.unauthorized({ message: 'Unauthorized access' })
})

可用的健康检查

以下是在 start/health.ts 文件中可以配置的可用健康检查列表。

DiskSpaceCheck

DiskSpaceCheck 计算服务器上的已用磁盘空间,并在超过某个阈值时报告警告/错误。

import { HealthChecks, DiskSpaceCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck()
])

默认情况下,警告阈值设置为 75%,失败阈值设置为 80%。但是,你也可以定义自定义阈值。

export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck()
.warnWhenExceeds(80) // 当使用超过 80% 时发出警告
.failWhenExceeds(90), // 当使用超过 90% 时失败
])

MemoryHeapCheck

MemoryHeapCheck 监控 process.memoryUsage() 方法报告的堆大小,并在超过某个阈值时报告警告/错误。

import { HealthChecks, MemoryHeapCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new MemoryHeapCheck()
])

默认情况下,警告阈值设置为 250MB,故障阈值设置为 300MB。不过,你也可以定义自定义阈值。

export const healthChecks = new HealthChecks().register([
new MemoryHeapCheck()
.warnWhenExceeds('300 mb')
.failWhenExceeds('700 mb'),
])

MemoryRSSCheck

MemoryRSSCheck 监控 process.memoryUsage() 方法报告的常驻集大小 (Resident Set Size),并在超过某个阈值时报告警告/错误。

import { HealthChecks, MemoryRSSCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new MemoryRSSCheck()
])

默认情况下,警告阈值设置为 320MB,故障阈值设置为 350MB。不过,你也可以定义自定义阈值。

export const healthChecks = new HealthChecks().register([
new MemoryRSSCheck()
.warnWhenExceeds('600 mb')
.failWhenExceeds('800 mb'),
])

DbCheck

DbCheck@adonisjs/lucid 包提供,用于监控与 SQL 数据库的连接。你可以按如下方式导入和使用它。

import db from '@adonisjs/lucid/services/db'
import { DbCheck } from '@adonisjs/lucid/database'
import { HealthChecks, DiskSpaceCheck, MemoryHeapCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
new DbCheck(db.connection()),
])

以下是数据库健康检查的示例报告。

Report sample
{
"name": "Database health check (postgres)",
"isCached": false,
"message": "Successfully connected to the database server",
"status": "ok",
"finishedAt": "2024-06-20T07:18:23.830Z",
"meta": {
"connection": {
"name": "postgres",
"dialect": "postgres"
}
}
}

DbCheck 类接受一个数据库连接以进行监控。如果你想监控多个连接,请为每个连接多次注册此检查。例如:

Monitoring multiple connections
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
new DbCheck(db.connection()),
new DbCheck(db.connection('mysql')),
new DbCheck(db.connection('pg')),
])

DbConnectionCountCheck

DbConnectionCountCheck 监控数据库服务器上的活动连接,并在超过某个阈值时报告警告/错误。此检查仅支持 PostgreSQLMySQL 数据库。

import db from '@adonisjs/lucid/services/db'
import { DbCheck, DbConnectionCountCheck } from '@adonisjs/lucid/database'
import { HealthChecks, DiskSpaceCheck, MemoryHeapCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
new DbCheck(db.connection()),
new DbConnectionCountCheck(db.connection())
])

以下是数据库连接数健康检查的示例报告。

Report sample
{
"name": "Connection count health check (postgres)",
"isCached": false,
"message": "There are 6 active connections, which is under the defined thresholds",
"status": "ok",
"finishedAt": "2024-06-20T07:30:15.840Z",
"meta": {
"connection": {
"name": "postgres",
"dialect": "postgres"
},
"connectionsCount": {
"active": 6,
"warningThreshold": 10,
"failureThreshold": 15
}
}
}

默认情况下,警告阈值设置为 10 个连接,故障阈值设置为 15 个连接。不过,你也可以定义自定义阈值。

new DbConnectionCountCheck(db.connection())
.warnWhenExceeds(4)
.failWhenExceeds(10)

RedisCheck

RedisCheck@adonisjs/redis 包提供,用于监控与 Redis 数据库(包括集群)的连接。你可以按如下方式导入和使用它。

import redis from '@adonisjs/redis/services/main'
import { RedisCheck } from '@adonisjs/redis'
import { HealthChecks, DiskSpaceCheck, MemoryHeapCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
new RedisCheck(redis.connection()),
])

以下是数据库健康检查的示例报告。

Report sample
{
"name": "Redis health check (main)",
"isCached": false,
"message": "Successfully connected to the redis server",
"status": "ok",
"finishedAt": "2024-06-22T05:37:11.718Z",
"meta": {
"connection": {
"name": "main",
"status": "ready"
}
}
}

RedisCheck 类接受一个 Redis 连接以进行监控。如果你想监控多个连接,请为每个连接多次注册此检查。例如:

Monitoring multiple connections
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
new RedisCheck(redis.connection()),
new RedisCheck(redis.connection('cache')),
new RedisCheck(redis.connection('locks')),
])

RedisMemoryUsageCheck

RedisMemoryUsageCheck 监控 Redis 服务器的内存使用情况,并在超过某个阈值时报告警告/错误。

import redis from '@adonisjs/redis/services/main'
import { RedisCheck, RedisMemoryUsageCheck } from '@adonisjs/redis'
import { HealthChecks, DiskSpaceCheck, MemoryHeapCheck } from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck(),
new MemoryHeapCheck(),
new RedisCheck(redis.connection()),
new RedisMemoryUsageCheck(redis.connection())
])

以下是来自 redis 内存使用情况健康检查的示例报告。

Report sample
{
"name": "Redis memory consumption health check (main)",
"isCached": false,
"message": "Redis 内存使用量为 1.06MB,低于定义的阈值",
"status": "ok",
"finishedAt": "2024-06-22T05:36:32.524Z",
"meta": {
"connection": {
"name": "main",
"status": "ready"
},
"memoryInBytes": {
"used": 1109616,
"warningThreshold": 104857600,
"failureThreshold": 125829120
}
}
}

默认情况下,警告阈值设置为 100MB,失败阈值设置为 120MB。但是,你也可以定义自定义阈值。

new RedisMemoryUsageCheck(db.connection())
.warnWhenExceeds('200MB')
.failWhenExceeds('240MB')

缓存结果

每次调用 healthChecks.run 方法(即访问 /health 端点)时,都会执行健康检查。你可能希望频繁地 ping /health 端点,但希望避免每次访问都执行某些检查。

例如,每分钟监控磁盘空间并不是很有用,但每分钟跟踪内存可能很有帮助。

因此,我们允许你在注册单个健康检查时缓存其结果。例如:

import {
HealthChecks,
MemoryRSSCheck,
DiskSpaceCheck,
MemoryHeapCheck,
} from '@adonisjs/core/health'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck().cacheFor('1 hour'),
new MemoryHeapCheck(), // 不缓存
new MemoryRSSCheck(), // 不缓存
])

创建自定义健康检查

你可以创建一个自定义健康检查,作为遵循 HealthCheckContract 接口的 JavaScript 类。你可以在项目或包的任何位置定义健康检查,并在 start/health.ts 文件中导入它以进行注册。

import { Result, BaseCheck } from '@adonisjs/core/health'
import type { HealthCheckResult } from '@adonisjs/core/types/health'
export class ExampleCheck extends BaseCheck {
async run(): Promise<HealthCheckResult> {
/**
* 以下检查仅供参考
*/
if (checkPassed) {
return Result.ok('要显示的成功消息')
}
if (checkFailed) {
return Result.failed('错误消息', errorIfAny)
}
if (hasWarning) {
return Result.warning('警告消息')
}
}
}

如上述示例所示,你可以使用 Result 类来创建健康检查结果。此外,你还可以按如下方式合并结果的元数据。

Result.ok('数据库连接正常').mergeMetaData({
connection: {
dialect: 'pg',
activeCount: connections,
},
})

注册自定义健康检查

你可以在 start/health.ts 文件中导入自定义健康检查类,并通过创建新的类实例来注册它。

import { ExampleCheck } from '../app/health_checks/example.js'
export const healthChecks = new HealthChecks().register([
new DiskSpaceCheck().cacheFor('1 hour'),
new MemoryHeapCheck(),
new MemoryRSSCheck(),
new ExampleCheck()
])