Terminus 기반 Health Check 방법 (NestJS)

이번 글에서는 Terminus를 활용해서 Health Check를 하는 방법에 대해 적어보겠습니다. 바로 이전에 적었던 글과 관련이 있는 내용이니 함께 읽어보시면 좋습니다.

NestJS 애플리케이션 내 Health Check 추가

Terminus 통합은 준비/활성 상태 확인을 제공합니다. 복잡한 백엔드 설정의 경우 상태 확인이 중요합니다. 간단히 말해서 웹 개발 영역의 상태 확인은 일반적으로 https://my-website.com/health/readiness와 같은 특수 주소로 구성됩니다. 인프라의 서비스 또는 구성 요소(예: Kubernetes)는 이 주소를 지속적으로 확인합니다.

이 주소에 대한 GET 요청에서 반환된 HTTP 상태 코드에 따라 서비스는 “비정상” 응답을 받을 때 조치를 취합니다. “정상” 또는 “비정상”의 정의는 제공하는 서비스 유형에 따라 다르므로 Terminus 통합은 일련의 상태 표시기로 사용자를 지원합니다.

예를 들어, 웹 서버가 MongoDB를 사용하여 데이터를 저장하는 경우 MongoDB가 계속 실행 중인지 여부는 중요한 정보입니다. 이 경우 MongooseHealthIndicator를 사용할 수 있습니다. 올바르게 구성된 경우(자세한 내용은 나중에 설명) 상태 확인 주소는 MongoDB가 실행 중인지 여부에 따라 정상 또는 비정상 HTTP 상태 코드를 반환합니다.

시작하기


@nestjs/terminus를 시작하려면 필요한 종속성을 설치해야 합니다.

$ npm install --save @nestjs/terminus

상태 확인 설정

상태 확인은 상태 지표의 요약을 나타냅니다. 상태 표시기는 정상 또는 비정상 상태인지 여부에 관계없이 서비스 검사를 실행합니다. 할당된 상태 표시기가 모두 실행 중이면 상태 확인이 긍정적입니다. 많은 애플리케이션에 유사한 상태 표시기가 필요하므로 @nestjs/terminus는 다음과 같은 미리 정의된 표시기 세트를 제공합니다.

  • HttpHealthIndicator
  • TypeOrmHealthIndicator
  • MongooseHealthIndicator
  • SequelizeHealthIndicator
  • MicroserviceHealthIndicator
  • GRPCHealthIndicator
  • MemoryHealthIndicator
  • DiskHealthIndicator

첫 번째 상태 확인을 시작하기 위해 HealthModule을 생성하고 TerminusModule을 imports 배열로 가져옵니다.

import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';

@Module({
  imports: [TerminusModule]
})
export class HealthModule {}

Nest CLI를 사용하여 쉽게 설정할 수 있는 컨트롤러를 사용하여 상태 확인을 실행할 수 있습니다.

$ nest g controller health

HTTP 상태 확인

@nestjs/terminus를 설치하고 TerminusModule을 가져오고 새 컨트롤러를 생성하면 상태 확인을 생성할 준비가 된 것입니다. HTTPHealthIndicator에는 @nestjs/axios 패키지가 필요하므로 패키지가 설치되어 있는지 확인하십시오.

$ npm i --save @nestjs/axios

이제 HealthController를 설정할 수 있습니다.

import { Controller, Get } from '@nestjs/common';
import { HealthCheckService, HttpHealthIndicator, HealthCheck } from '@nestjs/terminus';

@Controller('health')
export class HealthController {
  constructor(
    private health: HealthCheckService,
    private http: HttpHealthIndicator,
  ) {}

  @Get()
  @HealthCheck()
  check() {
    return this.health.check([
      () => this.http.pingCheck('nestjs-docs', 'https://docs.nestjs.com'),
    ]);
  }
}
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { HttpModule } from '@nestjs/axios';
import { HealthController } from './health.controller';

@Module({
  imports: [TerminusModule, HttpModule],
  controllers: [HealthController],
})
export class HealthModule {}

이제 상태 확인에서 https://docs.nestjs.com 주소로 GET 요청을 보냅니다. 해당 주소에서 정상적인 응답을 받으면 http://localhost:3000/health의 경로는 200 상태 코드와 함께 다음 개체를 반환합니다.

{
  "status": "ok",
  "info": {
    "nestjs-docs": {
      "status": "up"
    }
  },
  "error": {},
  "details": {
    "nestjs-docs": {
      "status": "up"
    }
  }
}

이 응답 개체의 인터페이스는 HealthCheckResult 인터페이스가 있는 @nestjs/terminus 패키지에서 액세스할 수 있습니다.

특정 HTTP 응답 코드 확인

경우에 따라 특정 기준을 확인하고 응답의 유효성을 검사할 수 있습니다. 예를 들어 https://my-external-service.com이 응답 코드 204를 반환한다고 가정해 보겠습니다. HttpHealthIndicator.responseCheck를 사용하면 해당 응답 코드를 구체적으로 확인하고 다른 모든 코드를 비정상으로 결정할 수 있습니다.

204 이외의 다른 응답 코드가 반환되는 경우 다음 예제는 비정상입니다. 세 번째 매개변수는 응답이 정상(true) 또는 비정상(false)으로 간주되는지 부울을 반환하는 함수(sync 또는 async)를 제공해야 합니다.

@Get()
@HealthCheck()
check() {
  return this.health.check([
    () =>
      this.http.responseCheck(
        'my-external-service',
        'https://my-external-service.com',
        (res) => res.status === 204,
      ),
  ]);
}

TypeOrm 상태 표시기

Terminus는 상태 확인에 데이터베이스 확인을 추가하는 기능을 제공합니다. 이 상태 표시기를 시작하려면 데이터베이스 장을 확인하고 애플리케이션 내에서 데이터베이스 연결이 설정되었는지 확인해야 합니다.

@Controller('health')
export class HealthController {
  constructor(
    private health: HealthCheckService,
    private db: TypeOrmHealthIndicator,
  ) {}

  @Get()
  @HealthCheck()
  check() {
    return this.health.check([
      () => this.db.pingCheck('database'),
    ]);
  }
}

데이터베이스에 연결할 수 있으면 이제 GET 요청으로 http://localhost:3000을 요청할 때 다음 JSON 결과가 표시됩니다.

{
  "status": "ok",
  "info": {
    "database": {
      "status": "up"
    }
  },
  "error": {},
  "details": {
    "database": {
      "status": "up"
    }
  }
}

앱이 여러 데이터베이스를 사용하는 경우 각 연결을 HealthController에 주입해야 합니다. 그런 다음 연결 참조를 TypeOrmHealthIndicator에 전달하기만 하면 됩니다.

@Controller('health')
export class HealthController {
  constructor(
    private health: HealthCheckService,
    private db: TypeOrmHealthIndicator,
    @InjectConnection('albumsConnection')
    private albumsConnection: Connection,
    @InjectConnection()
    private defaultConnection: Connection,
  ) {}

  @Get()
  @HealthCheck()
  check() {
    return this.health.check([
      () => this.db.pingCheck('albums-database', { connection: this.albumsConnection }),
      () => this.db.pingCheck('database', { connection: this.defaultConnection }),
    ]);
  }
}

디스크 상태 표시기

DiskHealthIndicator를 사용하면 사용 중인 스토리지의 양을 확인할 수 있습니다. 시작하려면 DiskHealthIndicator를 HealthController에 삽입해야 합니다. 다음 예는 / 경로에 사용된 스토리지를 확인합니다(또는 Windows에서는 C:\\를 사용할 수 있음). 총 스토리지 공간의 50% 이상을 초과하면 비정상 상태 확인으로 응답합니다.

@Controller('health')
export class HealthController {
  constructor(
    private readonly health: HealthCheckService,
    private readonly disk: DiskHealthIndicator,
  ) {}

  @Get()
  @HealthCheck()
  check() {
    return this.health.check([
      () => this.disk.checkStorage('storage', { path: '/', thresholdPercent: 0.5 }),
    ]);
  }
}

DiskHealthIndicator.checkStorage 함수를 사용하면 고정된 공간 양을 확인할 수도 있습니다. 다음 예제는 /my-app/ 경로가 250GB를 초과하는 경우 비정상입니다.

@Get()
@HealthCheck()
check() {
  return this.health.check([
    () => this.disk.checkStorage('storage', {  path: '/', threshold: 250 * 1024 * 1024 * 1024, })
  ]);
}
error: Content is protected !!