Health checks (Terminus)

Health checks (Terminus)

terminus는 정상적인 종료에 반응하기위한 후크를 제공하며 모든 HTTP 응용 프로그램에 대한 적절한 Kubernetes readiness/liveness 확인을 생성하도록 지원합니다. @nestjs/terminus 모듈은 터미널 라이브러리를 Nest 에코 시스템과 통합합니다.

Getting started

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

$ npm install --save @nestjs/terminus @godaddy/terminus

Setting up a health check

상태 확인은 상태 표시기의 요약을 나타냅니다. 상태 표시기는 서비스 상태에 관계없이 서비스 검사를 실행합니다. 할당된 모든 상태 표시기가 작동되어 실행중인 경우 상태 확인은 긍정적입니다. 많은 응용 프로그램이 유사한 상태 표시기를 필요로 하기 때문에 @nestjs/terminus는 다음과 같은 미리 정의된 상태 표시기 집합을 제공합니다.

  • DNSHealthIndicator

  • TypeOrmHealthIndicator

  • MongooseHealthIndicator

  • MicroserviceHealthIndicator

  • MemoryHealthIndicator

  • DiskHealthIndicator

DNS Health Check

첫번째 상태 확인을 시작하는 첫번째 단계는 상태 표시기를 엔드 포인트에 연결하는 서비스를 설정하는 것입니다.

@@filename(terminus-options.service)
import {
  TerminusEndpoint,
  TerminusOptionsFactory,
  DNSHealthIndicator,
  TerminusModuleOptions
} from '@nestjs/terminus';
import { Injectable } from '@nestjs/common';

@Injectable()
export class TerminusOptionsService implements TerminusOptionsFactory {
  constructor(
    private readonly dns: DNSHealthIndicator,
  ) {}

  createTerminusOptions(): TerminusModuleOptions {
    const healthEndpoint: TerminusEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dns.pingCheck('google', 'https://google.com'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}
@@switch
import { Injectable, Dependencies } from '@nestjs/common';
import { DNSHealthIndicator } from '@nestjs/terminus';

@Injectable()
@Dependencies(DNSHealthIndicator)
export class TerminusOptionsService {
  constructor(dns) {
    this.dns = dns;
  }

  createTerminusOptions() {
    const healthEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dns.pingCheck('google', 'https://google.com'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}

일단 TerminusOptionsService를 설정하면, TerminusModule을 루트 ApplicationModule로 가져올 수 있습니다. TerminusOptionsService는 설정을 제공하며,이 설정은 TerminusModule에 의해 사용됩니다.

@@filename(app.module)
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { TerminusOptionsService } from './terminus-options.service';

@Module({
  imports: [
    TerminusModule.forRootAsync({
      useClass: TerminusOptionsService,
    }),
  ],
})
export class ApplicationModule { }

info 힌트 올바르게 수행되면 Nest는 GET 요청을 통해 정의 된 경로에 도달 할 수있는 정의 된 상태 점검을 노출합니다. 예를 들어 curl -X GET 'http://localhost:3000/health'

Custom health indicator

경우에 따라 @nestjs/terminus에서 제공하는 사전 정의된 상태 표시기가 모든 상태 확인 요구 사항을 다루지 않습니다. 이 경우 필요에 따라 사용자 정의 상태 표시기를 설정할 수 있습니다.

맞춤형 상태 확인을 나타내는 서비스를 만들어 시작하겠습니다. 상태 확인이 어떻게 구성되어 있는지에 대한 기본 지식을 얻기 위해 DogHealthIndicator 예제를 만들 것입니다. 모든 Dog 오브젝트에 goodboy 유형이 있는 경우이 Health 표시기의 상태는 "up"이어야 합니다. 그렇지 않으면 오류가 발생하고 Health 표시기는 "down"으로 표시됩니다.

@@filename(dog.health)
import { Injectable } from '@nestjs/common';
import { HealthCheckError } from '@godaddy/terminus';
import { HealthIndicatorResult } from '@nestjs/terminus';

export interface Dog {
  name: string;
  type: string;
}

@Injectable()
export class DogHealthIndicator extends HealthIndicator {
  private readonly dogs: Dog[] = [
    { name: 'Fido', type: 'goodboy' },
    { name: 'Rex', type: 'badboy' },
  ];

  async isHealthy(key: string): Promise<HealthIndicatorResult> {
    const badboys = this.dogs.filter(dog => dog.type === 'badboy');
    const isHealthy = badboys.length === 0;
    const result = this.getStatus(key, isHealthy, { badboys: badboys.length });

    if (isHealthy) {
      return result;
    }
    throw new HealthCheckError('Dogcheck failed', result);
  }
}
@@switch
import { Injectable } from '@nestjs/common';
import { HealthCheckError } from '@godaddy/terminus';

@Injectable()
export class DogHealthIndicator extends HealthIndicator {
  dogs = [
    { name: 'Fido', type: 'goodboy' },
    { name: 'Rex', type: 'badboy' },
  ];

  async isHealthy(key) {
    const badboys = this.dogs.filter(dog => dog.type === 'badboy');
    const isHealthy = badboys.length === 0;
    const result = this.getStatus(key, isHealthy, { badboys: badboys.length });

    if (isHealthy) {
      return result;
    }
    throw new HealthCheckError('Dogcheck failed', result);
  }
}

다음으로 해야 할 일은 상태 표시기를 공급자로 등록하는 것입니다.

@@filename(app.module)
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { TerminusOptions } from './terminus-options.service';
import { DogHealthIndicator } from './dog.health.ts';

@Module({
  imports: [
    TerminusModule.forRootAsync({
      imports: [ApplicationModule],
      useClass: TerminusOptionsService,
    }),
  ],
  providers: [DogHealthIndicator],
  exports: [DogHealthIndicator],
})
export class ApplicationModule { }

info 힌트 실제 응용 프로그램에서 DogHealthIndicator는 별도의 모듈 (예: DogsModule)로 제공되어야하며, 그런 다음 ApplicationModule에서 가져옵니다. 그러나 DogHealthIndicatorDogModuleexports 배열에 추가하고 TerminusModule.forRootAsync()파라미터 객체의 imports 배열에 DogModule을 추가해야합니다.

마지막으로 해야 할 일은 필요한 상태 점검 엔드 포인트에 사용 가능한 상태 표시기를 추가하는 것입니다. 이를 위해 우리는 TerminusOptionsService로 돌아가서/health 엔드 포인트를 구현합니다.

@@filename(terminus-options.service)
import {
  TerminusEndpoint,
  TerminusOptionsFactory,
  DNSHealthIndicator,
  TerminusModuleOptions
} from '@nestjs/terminus';
import { Injectable } from '@nestjs/common';

@Injectable()
export class TerminusOptionsService implements TerminusOptionsFactory {
  constructor(
    private readonly dogHealthIndicator: DogHealthIndicator
  ) {}

  createTerminusOptions(): TerminusModuleOptions {
    const healthEndpoint: TerminusEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dogHealthIndicator.isHealthy('dog'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}
@@switch
import { DogHealthIndicator } from '../dog/dog.health';
import { Injectable, Dependencies } from '@nestjs/common';

@Injectable()
@Dependencies(DogHealthIndicator)
export class TerminusOptionsService {
  constructor(dogHealthIndicator) {
    this.dogHealthIndicator = dogHealthIndicator;
  }

  createTerminusOptions() {
    const healthEndpoint = {
      url: '/health',
      healthIndicators: [
        async () => this.dogHealthIndicator.isHealthy('dog'),
      ],
    };
    return {
      endpoints: [healthEndpoint],
    };
  }
}

모든 것이 올바르게 완료 되었다면/health 엔드 포인트는 503 응답 코드와 다음 데이터로 응답해야 합니다.

{
  "status": "error",
  "error": {
    "dog": {
      "status": "down",
      "badboys": 1
    }
  }
}

@nestjs/terminus 저장소에서 실제 예제를 볼 수 있습니다.

Custom Logger

Terminus 모듈은 상태 확인 요청 동안 모든 오류를 자동으로 기록합니다. 기본적으로 전역 적으로 정의 된 Nest 로거를 사용합니다. 글로벌 로거에 대한 자세한 내용은 로거 챕터에서 확인할 수 있습니다. 경우에 따라Terminus의 로그를 명시적으로 처리하려고 합니다. 이 경우 TerminusModule.forRoot[Async]함수는 커스텀 로거를위한 옵션을 제공합니다.

TerminusModule.forRootAsync({
  logger: (message: string, error: Error) => console.error(message, error),
  endpoints: [
    ...
  ]
})

로거 옵션을 null로 설정하여 로거를 비활성화 할 수도 있습니다.

TerminusModule.forRootAsync({
  logger: null,
  endpoints: [
    ...
  ]
})

Last updated