前提
BFF(Backend For Frontend)は、フロントエンドとバックエンドの間に位置する特定のタイプのサーバーとして機能し、フロントエンドとバックエンドのコミュニケーションを効率化します。この記事では、BFFとして機能するNestJSプロジェクトをAmazon ECS(Amazon Elastic Container Service)にデプロイする際のヘルスチェックAPIの実装について説明します。ヘルスチェックはサービスの健全性を監視し、問題が発生した場合に迅速に対応できるようにします。Amazon ECSでは、ヘルスチェックは必須の要件であり、失敗するとサービスが停止します。
実装
NestJSプロジェクトでは、ヘルスチェックコントローラを作成するだけでなく、ルートモジュールにヘルスチェックコントローラを含むモジュールを追加するか、ヘルスチェックコントローラを直接追加するかのいずれかが必要です。これにより、サービスの健全性を効果的に監視できます。
ヘルスチェックコントローラ
- HealthCheckService: ヘルスチェックのロジックをカプセル化します。
- HttpHealthIndicator: HTTPサービスのヘルスチェックを支援します。
- HealthCheck: 特定のメソッドがヘルスチェックエンドポイントとして機能することを示します。この例では、checkメソッドがヘルスチェックエンドポイントとして機能し、/healthエンドポイントにHTTP GETリクエストが送信されたときに呼び出されます。このメソッドはGraphQLサーバのヘルスチェックを行い、その結果をレスポンスとして返します。
health.controller.ts
import { Controller, Get } from "@nestjs/common";
import {
HealthCheckService,
HttpHealthIndicator,
HealthCheck,
} from "@nestjs/terminus";
import { AxiosResponse } from "@nestjs/terminus/dist/health-indicator/http/axios.interfaces";
type GraphQLHealthResponse = {
status: string;
};
@Controller("health")
export class HealthController {
constructor(
private health: HealthCheckService,
private http: HttpHealthIndicator,
) {}
@Get()
@HealthCheck()
check() {
return this.health.check([
() =>
this.http.pingCheck(
"GraphQL",
// ECSにデプロイしたら環境変数はタスク定義によってBFFエンドポイントを指定します
`${process.env.APP_URL}/.well-known/apollo/server-health`,
),
() =>
this.http.responseCheck(
"GraphQL",
// ECSにデプロイしたら環境変数はタスク定義によってBFFエンドポイントを指定します
`${process.env.APP_URL}/.well-known/apollo/server-health`,
function (res: AxiosResponse<GraphQLHealthResponse>) {
return res.data?.status === "pass";
},
),
]);
}
}
ヘルスチェックモジュール
- HttpModule: HTTPリクエストを行うためのモジュールです。
health.module.ts
import { Module } from "@nestjs/common";
import { HttpModule } from "@nestjs/axios";
import { HealthController } from "@/controller/health.controller";
import { HealthCheckService, HttpHealthIndicator } from "@nestjs/terminus";
@Module({
imports: [HttpModule],
providers: [
HealthCheckService,
HttpHealthIndicator,
],
controllers: [HealthController],
})
export class HealthModule {}
ルートモジュール
- GraphQLModule: GraphQLサーバを設定します。
- ConfigModule: アプリケーションの設定を管理します。
- TerminusModule: ヘルスチェックとグレースフルシャットダウンのサポートを提供します。
- join: パスを結合するためのユーティリティ関数です。
app.module.ts
import { HealthModule } from "@/modules/health/health.module";
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { GraphQLModule } from "@nestjs/graphql";
import { TerminusModule } from "@nestjs/terminus";
import { join } from "path";
@Module({
imports: [
GraphQLModule.forRoot({
autoSchemaFile: join(process.cwd(), "src/schema.gql"),
sortSchema: true,
}),
ConfigModule.forRoot({
envFilePath: [".env"],
}),
TerminusModule,
HealthModule,
],
})
export class AppModule {}
自らの備忘録のために投稿してますが、なにかお役に立てましたら幸いです!
また、なにか間違ってましたらご指摘いただけますと幸いです!