巣によるマイクロサービスの構築JSは簡単です!


ネスト.JSはプログレッシブノードです.効率的で信頼性が高く,スケーラブルなサーバサイドアプリケーションを構築するためのJSフレームワークこの定義は、非常に正確ですが、いつネストを使用するかを示しません.次のプロジェクトのJS、そしてその問題に光を投げるようにします.
ネスト.それは便利な機能の茄多さを提供するように、JSはバックエンド(私の友人の1つとして)の角度として見られることができます-と角度だけで一目で圧倒的にすることができますように.情報をオーバーロードするのを避けるために、私は私の観点から最も重要なものにスキップします.
  • PHPスクリプトでビルド
  • ボックスからサポートされている多くのテクノロジ( Graphql , Redis , AnthicSearch , Type , MicroService , CQRS ,
  • ノードをビルドします.JSと両方の表現をサポートします.JSとFastify
  • 依存性注入
  • 建築(上)
  • 巣のコア概念js


    まだネストに慣れていない場合.JSには、3つの基本的な概念は、すべての時間を動作されますModules , Controllers , and Services .

    モジュール


    モジュールは、再利用可能なコード(コンポーネント)にロジックをカプセル化します.
    // app.module.ts
    
    @Module({
      imports: [],       // Other modules
      controllers: [],   // REST controllers
      providers: [],     // Services, Pipes, Guards, etc
    })
    
    export class AppModule {}
    

    コントローラ


    REST操作( HTTPメソッド)を扱うために使用します.
    // app.controller.ts
    
    @Controller()      // Decorator indicating that the following TypeScript class is a REST controller
    export class AppController {
      constructor(private readonly appService: AppService) {}    // Service available through Dependency Injection  
    
      @Get()     // HTTP method handler
      getHello(): string {
        return this.appService.getHello();     // Calling a service method
      }
    }
    

    サービス


    サービスはロジックと機能を扱うために使用されます.コントローラの中からサービスメソッドが呼び出されます.
    // app.service.ts
    
    @Injectable()       // Decorator that marks a TypeScript class a provider (service)
    export class AppService {
      constructor() {}       // Other services, repositories, CQRS handlers can be accessed through Dependency Injection
    
      getHello(): string {
        return 'Hello World!';      // Plain functionality
      }
    }
    

    マイクロサービス


    そこにあるマイクロサービスに関するクリスリチャードソンによる素晴らしい記事シリーズがありますhttps://microservices.io/ . あなたはこの概念に精通していない場合は最初にそれを読んでください.
    を、コードにジャンプしましょう!次の2つのリポジトリが必要になります.
  • https://github.com/Baroshem/nest-demo
  • https://github.com/Baroshem/nest-microservice
  • それらをクローン化し、必要なすべての依存関係をインストールしてください.また、私たちのシステムにインストールされているDockerと、お好みのデータベース管理ツールを必要としますTable Plus ). また、エンドポイントをテストするのに郵便屋が必要です.

    リファクタリング基本サーバとマイクロサービス


    この節では、2つの基本的な巣を変換します.メインサーバ(APIゲートウェイ)とMicroService(アイテム操作を扱う責任)へのJSサーバー.
    いくつかの点で失われた場合は、リポジトリの内部にはコミットと分岐があります.

    リポジトリ


    簡単な例として提供する準備ができている2つのリポジトリがあり、非常に類似した巣です.小さな違いのJSサーバーnest-microservice :
  • .env.example コピーする環境変数を持つファイル.env ファイルをdocker-compose.yml 働く.
  • # Database
    POSTGRES_VERSION=13-alpine
    POSTGRES_USERNAME=postgres_user
    POSTGRES_PASSWORD=postgres_password
    POSTGRES_DATABASE=item
    POSTGRES_PORT=5433
    POSTGRES_HOST=localhost
    
  • docker-compose.yml PostgreSQLイメージの設定ファイルをデータベースに提供します.
  • // docker-compose.yml
    
    version: '3.7'
    services:
      postgres:
        container_name: microservice_postgres
        image: postgres:${POSTGRES_VERSION}
        environment: 
          - POSTGRES_USER=${POSTGRES_USERNAME}
          - POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
          - POSTGRES_DB=${POSTGRES_DATABASE}
        ports:
          - ${POSTGRES_PORT}:5432
        volumes:
          - /data/postgres/
        networks:
          - microservice-network
    
    networks: 
        microservice-network:
            driver: bridge
    
  • 必要なNPMパッケージが動作するデモ.
  • // package.json
    
    ...
      "dependencies": {
        "@nestjs/common": "^7.6.15",
        "@nestjs/config": "^0.6.3",
        "@nestjs/core": "^7.6.15",
        "@nestjs/microservices": "^7.6.15",
        "@nestjs/platform-express": "^7.6.15",
        "@nestjs/typeorm": "^7.1.5",
        "pg": "^8.6.0",
        "reflect-metadata": "^0.1.13",
        "rimraf": "^3.0.2",
        "rxjs": "^6.6.6",
        "typeorm": "^0.2.32"
      },
    
    nest-demo :
  • 必要なNPMパッケージが動作するデモ.
  • // package.json
    
    ...
      "dependencies": {
        "@nestjs/common": "^7.6.15",
        "@nestjs/config": "^0.6.3",
        "@nestjs/core": "^7.6.15",
        "@nestjs/microservices": "^7.6.15",
        "@nestjs/platform-express": "^7.6.15",
        "reflect-metadata": "^0.1.13",
        "rimraf": "^3.0.2",
        "rxjs": "^6.6.6"
      },
    
    両方のプロジェクトは基本的な巣です.jsサーバー
    // main.ts
    
    import { NestFactory } from '@nestjs/core';
    import { AppModule } from './app.module';
    
    async function bootstrap() {
      const app = await NestFactory.create(AppModule);
      await app.listen(3000);
    }
    bootstrap();
    
    // app.module.ts
    
    import { Module } from '@nestjs/common';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    
    @Module({
      imports: [],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule {}
    
    // app.controller.ts
    
    import { Controller, Get } from '@nestjs/common';
    import { AppService } from './app.service';
    
    @Controller()
    export class AppController {
      constructor(private readonly appService: AppService) {}
    
      @Get()
      getHello(): string {
        return this.appService.getHello();
      }
    }
    
    // app.service.ts
    
    import { Injectable } from '@nestjs/common';
    
    @Injectable()
    export class AppService {
      getHello(): string {
        return 'Hello World!';
      }
    }
    
    
    これらのサーバを使用するならyarn dev or npm run dev ブラウザで見るコマンドHello World .

    ここで、実際のリファクタリング


    このセクションで行うのは、基本サーバからコードを取り出し、APIゲートウェイとマイクロサービスにリファクタします.あなたはまだAPIゲートウェイの概念に精通していない場合は、それについての素晴らしい記事がクリスリチャードソンhttps://microservices.io/patterns/apigateway.html .

    ネスト

  • 内部app.module.ts 我々のサーバにTCP接続を使用してマイクロサービスに通信できるようにするために、いくつかのオプションを備えたクライアントモジュールを追加します.
  • // app.module.ts
    
    import { Module } from '@nestjs/common';
    import { ClientsModule, Transport } from '@nestjs/microservices';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    
    @Module({
      imports: [
        ClientsModule.register([{ name: 'ITEM_MICROSERVICE', transport: Transport.TCP }])
      ],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule {}
    
  • 内部app.controller.ts 読み書き機能をテストできる2つの新しいエンドポイントを追加します.
  • // app.controller.ts
    
    import { Body, Controller, Get, Param, Post } from '@nestjs/common';
    import { AppService } from './app.service';
    
    @Controller()
    export class AppController {
      constructor(private readonly appService: AppService) {}
    
      @Get()
      getHello(): string {
        return this.appService.getHello();
      }
    
      @Get('/item/:id')
      getById(@Param('id') id: number) {
        return this.appService.getItemById(id);
      }
    
      @Post('/create')
      create(@Body() createItemDto) {
        return this.appService.createItem(createItemDto);
      }
    }
    
  • 内部app.service.ts 我々は、メッセージパターンとデータを対応するマイクロサービスに送ることによって、新しい終点を扱う2つのさらなる方法を加えます.
  • // app.service.ts
    
    import { Inject, Injectable } from '@nestjs/common';
    import { ClientProxy } from '@nestjs/microservices';
    
    @Injectable()
    export class AppService {
      constructor(
        @Inject('ITEM_MICROSERVICE') private readonly client: ClientProxy
      ) {}
    
      getHello(): string {
        return 'Hello World!';
      }
    
      createItem(createItemDto) {
        return this.client.send({ role: 'item', cmd: 'create' }, createItemDto);
      }
    
      getItemById(id: number) {
        return this.client.send({ role: 'item', cmd: 'get-by-id' }, id); 
      }
    }
    
    ここでは、我々は注射しているITEM_MICROSERVICE 我々が宣言したクライアントapp.module.ts 後でメッセージを送るために、特定のメソッドでそれを使用するために.send メソッドは2つの引数を受け取ります;messagePattern 物の形でdata .
    **複数の変数を渡す必要がある場合(つまり、複数の変数を渡す必要がある場合).firstName and lastName ) オブジェクトを作成し、その形式で2番目の引数として送信します.
    値を覚えたりコピーしたりするようにしてくださいmessagePattern このメッセージに対応するために、MicroServiceでその正確な形でそれを必要とするので.
    そしてそれはnest-demo プロジェクトMicroServiceがまだリクエストを処理する準備ができていないので、プロジェクトを実行しないでください.

    ネスト

  • クリエイトitem.entity.ts ファイル.これは、データベーステーブルをモデル化するために使用されます.
  • // item.entity.ts
    
    import { BaseEntity, Column, Entity, PrimaryGeneratedColumn } from "typeorm";
    
    @Entity()
    export class ItemEntity extends BaseEntity {
        @PrimaryGeneratedColumn()
        id: number;
    
        @Column()
        name: string;
    }
    
    ここでは2列のテーブルを宣言しますid and name .
  • クリエイトitem.repository.ts データベース上のエンティティで動作できるファイル(作成、検索、削除など).
  • // item.repository.ts
    
    import { EntityRepository, Repository } from "typeorm";
    import { ItemEntity } from "./item.entity";
    
    @EntityRepository(ItemEntity)
    export class ItemRepository extends Repository<ItemEntity> {}
    
    ここでは、エンティティを扱うためのメソッドを作成することができますが、このチュートリアルではtypeorm .
  • 変更するapp.module PostgreSQLデータベースDockerコンテナと負荷に接続するにはItemRepository and ItemEntity .
  • // app.module.ts
    
    import { Module } from '@nestjs/common';
    import { TypeOrmModule } from '@nestjs/typeorm';
    import { AppController } from './app.controller';
    import { AppService } from './app.service';
    import { ItemEntity } from './item.entity';
    import { ItemRepository } from './item.repository';
    
    @Module({
      imports: [
        TypeOrmModule.forRoot({
          type: 'postgres',
          host: 'localhost',
          port: 5433,
          username: 'postgres_user',
          password: 'postgres_password',
          database: 'item',
          synchronize: true,
          autoLoadEntities: true,
        }),
        TypeOrmModule.forFeature([ItemRepository, ItemEntity])
      ],
      controllers: [AppController],
      providers: [AppService],
    })
    export class AppModule {}
    
    ****実際のアプリケーションでは、明示的な値で資格情報を使用しないでください.環境変数や@nestjs/config パッケージ.
  • リファクタmain.ts 基本ネストからのファイル.ネストするJSサーバー.JSマイクロサービス.
  • // main.ts
    
    import { NestFactory } from '@nestjs/core';
    import { Logger } from '@nestjs/common';
    import { Transport } from '@nestjs/microservices';
    
    import { AppModule } from './app.module';
    
    const logger = new Logger('Microservice');
    
    async function bootstrap() {
      const app = await NestFactory.createMicroservice(AppModule, {
        transport: Transport.TCP,
      });
    
      await app.listen(() => {
        logger.log('Microservice is listening');
      });
    }
    bootstrap();
    
  • リファクタapp.controller.ts HTTPメソッドではなく、メッセージを聞くには、ここで必要です.
  • // app.controller.ts
    
    import { Body, Controller, Get, Param, Post } from '@nestjs/common';
    import { MessagePattern } from '@nestjs/microservices';
    import { AppService } from './app.service';
    
    @Controller()
    export class AppController {
      constructor(private readonly appService: AppService) {}
    
      @Get()
      getHello(): string {
        return this.appService.getHello();
      }
    
      @MessagePattern({ role: 'item', cmd: 'create' })
      createItem(itemDto) {
        return this.appService.createItem(itemDto)
      }
    
      @MessagePattern({ role: 'item', cmd: 'get-by-id' })
      getItemById(id: number) {
        return this.appService.getItemById(id);
      }
    }
    
    ここでは、巣のデモからMessagePatternを使用して、特定のパターンを持つメッセージに対して反応します.
  • リファクタapp.service 読み書きメソッドを処理するには
  • // app.service.ts
    
    import { Injectable } from '@nestjs/common';
    import { ItemEntity } from './item.entity';
    import { ItemRepository } from './item.repository';
    
    @Injectable()
    export class AppService {
      constructor(
        private readonly itemRepository: ItemRepository,
      ) {}
    
      getHello(): string {
        return 'Hello World!';
      }
    
      createItem(itemDto) {
        const item = new ItemEntity();
        item.name = itemDto.name;
        return this.itemRepository.save(item);
      }
    
      getItemById(id) {
        return this.itemRepository.findOne(id);
      }
    }
    
    ここでは、注入を使用しているitemRepository 新しいを保存するItemEntity またはIDによって既存の1つを見つける.

    すべてのAPIゲートウェイ、マイクロサービスおよびデータベースコンテナの実行


    すべてのサービスを実行するには、dockerデスクトップを使用していない場合、2つのターミナルウィンドウまたは3つを開くことをお勧めします.
  • PostgreSQLコンテナを使用して実行するdocker-compose up インnest-microservice プロジェクトまたはDockerデスクトップを使用します.
  • ランyarn dev or npm run dev インnest-microservice マイクロサービスを開始するプロジェクト
  • ランyarn dev or npm run dev インnest-demo APIゲートウェイを起動するプロジェクト.
  • すべてが正しく動作しているかどうかをテストする

  • TablePlusを使用してPostgreSQLコンテナに接続し、巣に使用したのと同じ資格情報を使用します.タイプモジュールのJSアプリケーション.
  • postmanのポストエンドポイントをトリガーするhttp://localhost:3000/create あなたのアイテムの名前を
  • あなたは、郵便配達人の応答とtableplusの新しい記録を見るべきです.
  • さらにテストするにはまた、GET要求を送信することができますhttp://localhost:3000/item/:id id : 1になります.そして、PostgreSQLから得た正しいアイテムオブジェクトを見るべきです.
  • 概要


    この記事の10分未満では、2つの基本的な巣をリファクタリングしました.APIゲートウェイとマイクロサービスへのJSサーバー.よくできた!
    しかし、このトピックをよりよく理解するためには、おそらくより多くの時間が必要でしょうが、これは巣のマイクロサービスのトピックへの堅固な導入です.js

    便利なリンク

  • https://docs.nestjs.com/microservices/basics
  • https://docs.nestjs.com/techniques/database
  • ボーナス:MicroServiceテンプレート


    あなたが巣のより高度な例に興味があるならば.JS MicroServices私はあなた自身のマイクロサービスを作成するために使用できるMicroServiceテンプレートを作成しました.
    https://github.com/otasoft/microservice-template
    It consists of:
  • PostgreSQLのタイプ
  • CQRS
  • ドメイン駆動設計
  • イベントソーシング
  • ヘルスチェック
  • 単体テスト
  • .ENVサポート
  • RabbitMQイベントバス接続
  • DockerfileとDockerの作成
  • ディレクトリディレクトリ
  • ワークフローと問題テンプレート