Tilføjelse af sundhedstjek i NestJS Application
Sundhedstjekkets slutpunkt giver detaljerne om, hvordan vores applikation klarer sig. I dette indlæg viser vi, hvordan du tilføjer sundhedstjek til din NestJS-applikation. Hvis du vil lære om aktivering af CORS i din NestJS-applikation, kan du læse mere om det her.
Hvorfor tilføje Health Checks?
Når du først har bygget og implementeret din applikation, skal du vide, om din applikation kører problemfrit på en nemmere måde uden at foretage nogle forretningslogiske applikationer. Sundhedstjek tilbyder en måde at kontrollere, om databasen kører problemfrit, din lagerdisk er i orden, og din applikationstjeneste kører efter hensigten.
Den vigtigste grund til, at du har brug for sundhedstjek, er, at du kan fortsætte med at overvåge din ansøgning. En metrikindsamlingstjeneste (som Micrometer) kan fortsætte med at validere applikationen. Det kan bekræfte, at der ikke er nogen software- eller hardwarefejl. Ethvert øjeblik, der er software- eller hardwarefejl, kan det udløse en meddelelse om manuel eller automatisk indgriben for at få applikationen tilbage på sporet. Dette forbedrer applikationens pålidelighed.
Sundhedstjek i NestJS-applikationen
I NestJS framework, Terminus
Biblioteket tilbyder en måde at integrere beredskabs-/live-sundhedstjek på. En tjeneste eller komponent af infrastruktur vil løbende ramme et GET-endepunkt. Tjenesten vil handle baseret på svaret.
Lad os komme igang. Vi tilføjer terminusbiblioteket til vores NestJS-applikation.
npm install @nestjs/terminus
.
Terminus-integration tilbyder yndefuld nedlukning samt Kubernetes paratheds-/liveness-tjek for http-applikationer. Liveness check fortæller, om containeren er oppe at køre. Et parathedstjek fortæller, om containeren er klar til at acceptere indgående anmodninger.
Vi vil også opsætte en række kontroller for database, hukommelse, disk og redis i dette indlæg for at vise, hvordan sundhedstjek fungerer.
Hvordan konfigurerer man et sundhedstjek i NestJS?
Når vi har tilføjet nestjs/terminus
pakke, kan vi oprette et sundhedstjek-slutpunkt og inkludere nogle foruddefinerede indikatorer. Disse indikatorer inkluderer HTTP check
, Database connectivity check
, Memory and Disk check
.
Afhængigt af hvilken ORM du bruger, nestjs
tilbyder nogle indbyggede pakker som TypeORM
eller Sequlize
sundhedstjekindikatorer.
Sundhedstjekket vil give os en kombination af indikatorer. Dette sæt indikatorer giver os oplysninger, der indikerer, hvordan vores applikation klarer sig.
DiskHealthIndicator
Lad os starte med, hvordan serverens harddisk klarer sig.
DiskHealthIndicator indeholder kontrollen for disklagring af den aktuelle maskine.
Når vi tilføjer DiskHealthIndicator
i vores sundhedskontroller vil vi tjekke for opbevaring som følger:
this.disk.checkStorage('diskStorage', { thresholdPercent: 0.5, path: 'C:\\'});
HttpHealthIndicator
HttpHealthIndicator vil give detaljerne om vores HTTP-applikation, og om den er oppe og køre. Eksplicit tilføjer vi @nestjs/axios
pakke til vores projekt.
npm install @nestjs/axios
.
Derudover. vi bruger pingCheck
metode til at bekræfte, om vi er i stand til at oprette forbindelse til applikationen.
this.http.pingCheck('Basic check', 'http://localhost:3000');
MemoryHealthIndicator
Overordnet set giver MemoryHealthIndicator detaljerne om hukommelsen på den maskine, som applikationen kører på.
this.memory.checkHeap('memory_heap', 300*1024*1024);
this.memory.checkRSS('memory_rss',300*1024*1024);
Databasesundhedstjek
Forudsat at din applikation bruger en database, skal du have et databasesundhedstjek. Efterfølgende nestjs/terminus
leverer databasesundhedstjek gennem ORM-pakker som TypeORM, Sequelize eller Mongoose. Som en del af denne demo vil vi oprette et tilpasset databasesundhedstjek, da vi bruger Prisma ORM.
NestJS-applikation
Under alle omstændigheder, lad os oprette nestjs-applikation med nestjs/cli
.
nest new healthcheckdemo
.
Som tidligere nævnt vil vi bruge Prisma ORM.
npm install prisma --save-dev
.
Dette vil installere Prisma cli. Hvis vi nu kører npx prisma init
, vil det skabe en barebone på schema.prisma
fil, hvor vi vil oprette vores databasemodelskema.
I denne applikation bruger jeg et simpelt skema, hvor en bruger kan tilmelde sig for at oprette indlæg. Jeg bruger også MySQL-databasen. Dette skema vil se ud som nedenstående:
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
engineType = "binary"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
}
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
posts Post[]
}
model Post {
id Int @default(autoincrement()) @id
title String
content String?
published Boolean? @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
}
Som standard vil Prisma oprette .env
fil, hvis den ikke var der før. Det vil også tilføje en standardvariabel for DATABASE_URL
.
Hvis vi kører npm run prisma migrate dev
, vil det skabe disse databasetabeller i vores DB.
Lad os desuden oprette et app-modul i vores eksempelapplikation til healthcheckdemo
.
import { Module } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserService } from './user.service';
import { HealthModule } from './health/health.module';
import { HttpModule } from '@nestjs/axios';
import { PrismaService } from './prisma.service';
@Module({
imports: [HealthModule, HttpModule],
controllers: [AppController],
providers: [AppService, UserService, PrismaClient, PrismaService,],
})
export class AppModule {}
Vi vil også oprette HealthModule, der tjener formålet for HealthControlleren.
import { Module } from '@nestjs/common';
import { TerminusModule } from '@nestjs/terminus';
import { PrismaService } from 'src/prisma.service';
import { HealthController } from './health.controller';
import { PrismaOrmHealthIndicator } from './prismaorm.health';
@Module({
imports: [
TerminusModule,
],
controllers: [HealthController],
providers: [ PrismaOrmHealthIndicator, PrismaService]
})
export class HealthModule {}
I dette HealthModule vil du bemærke, at der er PrismaOrmHealthIndicator. Før vi dykker ned i PrismaOrmHealthIndicator
, skal vi generere Prisma Client
.
npm install @prisma/client
genererer Prisma-klienten til din databasemodel. Dette vil afsløre CRUD-operationer for din databasemodel, hvilket gør det nemmere for udviklere at fokusere på forretningslogik frem for hvordan man får adgang til data fra en database.
Vi vil abstrahere Prisma Client API'er for at oprette databaseforespørgsler i en separat tjeneste PrismaService
. Denne service vil også instansiere Prisma Client.
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
});
}
}
Der er et dokumenteret problem med enableShutdownHooks. Vi bruger enableShutdownHooks
ring, når du lukker applikationen.
Sundhedscontroller
Til et sundhedstjek skal vi have en sundhedskontrollant. Vi talte om sundhedsmodulet i det foregående afsnit. Der er to vigtige dele tilbage, før vi viser, hvordan sundhedstjekket vil se ud.
Lad os oprette en sundhedscontroller.
nest g controller health
Dette vil generere en controller til os.
import { Controller, Get, Inject } from '@nestjs/common';
import { DiskHealthIndicator, HealthCheck, HealthCheckService, HttpHealthIndicator, MemoryHealthIndicator, MicroserviceHealthIndicator } from '@nestjs/terminus';
import { PrismaOrmHealthIndicator } from './prismaorm.health';
@Controller('health')
export class HealthController {
constructor(
private health: HealthCheckService,
private http: HttpHealthIndicator,
@Inject(PrismaOrmHealthIndicator)
private db: PrismaOrmHealthIndicator,
private disk: DiskHealthIndicator,
private memory: MemoryHealthIndicator,
) {}
@Get()
@HealthCheck()
check() {
return this.health.check([
() => this.http.pingCheck('basic check', 'http://localhost:3000'),
() => this.disk.checkStorage('diskStorage', { thresholdPercent: 0.5, path: 'C:\\'}),
() => this.db.pingCheck('healthcheckdemo'),
() => this.memory.checkHeap('memory_heap', 300*1024*1024),
() => this.memory.checkRSS('memory_rss', 300*1024*1024),
// Mongoose for MongoDB check
// Redis check
]);
}
}
I sundhedscontrolleren har vi et GET-slutpunkt /health
for at give detaljer om, hvordan vores applikation, maskinens hukommelse, lagerdisken og databaser klarer sig. NestJs
tilbyder ikke nogen ORM Health-indikator for Prisma. Så jeg skriver en brugerdefineret indikator for at finde ud af databasens sundhed.
I det store og hele vil denne tilpassede Prisma-sundhedsindikator være:
import { Injectable, InternalServerErrorException } from "@nestjs/common";
import { HealthIndicator, HealthIndicatorResult } from "@nestjs/terminus";
import { PrismaService } from "src/prisma.service";
@Injectable()
export class PrismaOrmHealthIndicator extends HealthIndicator {
constructor(private readonly prismaService: PrismaService) {
super();
}
async pingCheck(databaseName: string): Promise {
try {
await this.prismaService.$queryRaw`SELECT 1`;
return this.getStatus(databaseName, true);
} catch (e) {
throw new InternalServerErrorException('Prisma check failed', e);
}
}
}
Vi udvider den abstrakte klasse HealthIndicator
og implementering af en metode kaldet pingCheck
i denne PrismaOrmHealthIndicator
klasse. Denne metode bruger PrismaService
for at forespørge på den database, der er blevet bestået. Vi bruger SELECT 1
forespørgsel. Hvis forespørgslen lykkes, får vi databasestatus som true
.
Bemærk også, at denne klasse PrismaOrmHealthIndicator
er injicerbar, og vi injicerer det i vores HealthController
.
Hvis vi nu starter applikationen og udfører slutpunktet, får vi svaret som nedenfor:
{
"status": "ok",
"info": {
"basic check": {
"status": "up"
},
"diskStorage": {
"status": "up"
},
"healthcheckdemo": {
"status": "up"
},
"memory_heap": {
"status": "up"
},
"memory_rss": {
"status": "up"
}
},
"error": {},
"details": {
"basic check": {
"status": "up"
},
"diskStorage": {
"status": "up"
},
"healthcheckdemo": {
"status": "up"
},
"memory_heap": {
"status": "up"
},
"memory_rss": {
"status": "up"
}
}
}
Som du kan se, ser alt ud til at køre fint. healthcheckdemo
er databasenavnet, som jeg bruger i MySQL.
På samme måde kan vi også tilføje redis
og mongoose
som en del af sundhedstjek i vores NestJS-applikation.
Konklusion
I dette indlæg opretter vi en simpel NestJS-applikation for at demonstrere, hvordan man tilføjer sundhedstjek. Koden til dette indlæg er tilgængelig her.
Hvis du har feedback til dette indlæg ELLER min bog Simplifying Spring Security, vil jeg meget gerne høre din feedback.