開発覚書はてな版

個人的な開発関連の備忘録

【NestJS】NestJSでgRPCを使ってみた - server編

概要

今回はNestJS上でgRPCサーバーを作成したサンプルです。

gRPCについては以下のページを参照 grpc.io

NestJSのgRPCの説明記事 docs.nestjs.com

実行環境

  • Node.js - 10.x

使用ライブラリ

  • @nestjs/core - 7.0.x
  • @nestjs/microservices - 7.0.x
  • grpc - 1.24.x

サンプルソース

src/proto/sample.proto

  • インターフェース定義
syntax = "proto3";

package sample;

service AppService {
  rpc FindOne (SampleDataById) returns (SampleData) {}
}

message SampleDataById {
  int32 id = 1;
}

message SampleData {
  int32 id = 1;
  string name = 2;
}

src/model.ts

  • TypeScript側で使用する型を定義。
export interface SampleDataById {
  id: number;
}

export interface SampleData {
  id: number;
  name: string;
}

src/app.controller.ts

  • @GrpcMethodproto/sample.proto 記載のサービス名を定義します。
  • メソッド名は proto/sample.proto 記載のサービス内のメソッド名にあわせます。
import { Controller } from '@nestjs/common';
import { GrpcMethod } from '@nestjs/microservices';

import { SampleData, SampleDataById } from './model';

@Controller()
export class AppController {
  @GrpcMethod('AppService')
  findOne(data: SampleDataById, metadata: any): SampleData {
    const items = [
      { id: 1, name: 'John' },
      { id: 2, name: 'Doe' },
    ] as SampleData[];
    const filteredItems = items.filter((item) => item.id === data.id);
    return filteredItems.length > 0 ? filteredItems[0] : ({} as SampleData);
  }
}

src/app.module.ts

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

import { AppController } from './app.controller';

@Module({
  controllers: [AppController],
})
export class AppModule {}

src/main.ts

  • NestFactory.createMicroservice メソッドで生成します。
  • Transport.GRPC を指定します。
  • protoPath に実際に定義したprotoファイルを指定します。
import { NestFactory } from '@nestjs/core';
import { Transport, GrpcOptions } from '@nestjs/microservices';
import { join } from 'path';

import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.createMicroservice<GrpcOptions>(AppModule, {
    transport: Transport.GRPC,
    options: {
      url: 'localhost:5000',
      package: 'sample',
      protoPath: join(__dirname, 'proto/sample.proto'),
    },
  });
  await app.listenAsync();
}
bootstrap();

nest-cli.json

  • protoファイルを出力先のフォルダーに出力するために assets の指定をします。
{
  "collection": "@nestjs/schematics",
  "sourceRoot": "src",
  "compilerOptions": {
    "assets": [
      "proto/**/*"
    ]
  }
}

実行結果

  • 以下のように動作します。 f:id:kakkoya:20200426180823g:plain

  • 動作確認のツールは以下のものを使用しています

github.com

サンプルソース一式

github.com

おわりに

  • 通信速度が速いのとインタフェース定義がわかりやすい。
  • なんとなくWSDLを思い出す。
  • そういえばTCPベースのWCFとか昔やったな・・・。開発しやすかったけどMicrosoft+VisualStudio前提だったから流行らなかったな・・・。
  • NestJS内で完結して開発が出来るので便利。NestJSの守備範囲が広すぎる。
  • サービス間通信としての使用が前提なので、ブラウザからのアクセスはgRPC-Gatewayなどで変換が必要。BFF形式のAPIを自作した方が良いかも。