banner
SlhwSR

SlhwSR

热爱技术的一名全栈开发者
github
bilibili

NestはFastifyに基づいてマイクロサービスアーキテクチャを実現します

私たちの会社では最近、多くの Java エンジニアがさまざまなマイクロサービスをフロントエンドから一つずつ呼び出す必要があり、こうするのは非常に面倒ではありませんか?

まず、なぜマイクロサービスを導入するのかについて説明します:
マイクロサービスアーキテクチャを組み合わせることで、システムの拡張性と信頼性を向上させるだけでなく、チームの効率的な協力と迅速な反復を促進し、複雑なビジネスシナリオにより良く対応できるようになります。

こうすることで、彼らのサービスと自分のビジネスを密接に結びつけることができます~

直接コードを示します:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import {
  FastifyAdapter,
  NestFastifyApplication,
} from '@nestjs/platform-fastify';
import { HkAuthMiddleware } from './hk-auth/hk-auth.middleware';
import { HttpService } from '@nestjs/axios';
import fastifyMultipart from '@fastify/multipart';
import cluster from 'cluster';
import * as os from 'os';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';

async function bootstrap() {
  // Fastify HTTP アプリケーションを作成
  const app = await NestFactory.create<NestFastifyApplication>(
    AppModule,
    new FastifyAdapter(),
  );

  // マイクロサービス接続を登録
  app.connectMicroservice<MicroserviceOptions>({
    transport: Transport.TCP,
    options: {
      host: process.env.SCREENSHOT_SERVICE_HOST || 'localhost',
      port: parseInt(process.env.SCREENSHOT_SERVICE_PORT || '4000'),
      retryAttempts: 5, // リトライ回数
      retryDelay: 3000, // リトライ遅延(ミリ秒)
    },
  });

  // マイクロサービス接続を起動
  await app.startAllMicroservices();

  // 現在の設定を保持
  const httpService = new HttpService();
  const authMiddleware = new HkAuthMiddleware(httpService);
  app.setGlobalPrefix(`/api`);
  await app.register(fastifyMultipart, {
    limits: {
      fileSize: 200 * 1024 * 1024,
    },
  });
  app.use((req, res, next) => authMiddleware.use(req, res, next));
  await app.enableCors();
  
  // HTTP サービスを起動
  await app.listen(3000, '0.0.0.0');
}

// 現在のクラスターモードを保持
if (cluster.isPrimary) {
  const cpuCount = os.cpus().length;
  console.log(`主プロセスが起動し、${cpuCount} 個のワーカープロセスをフォークする準備ができました`);
  for (let i = 0; i < cpuCount; i++) {
    cluster.fork();
  }
  cluster.on('exit', (worker) => {
    console.log(`ワーカープロセス ${worker.process.pid} が終了しました。再起動中...`);
    cluster.fork();
  });
} else {
  bootstrap();
}

ここでマイクロサービスの登録について説明します。あなた自身が店舗を開いて、他の人があなたの店舗でさまざまなサービスを購入できると考えてください。

したがって、host はあなたのサーバーの IP、port、およびマイクロサービスを開くポートを表します。

これにより、アプリケーションをマイクロサービスアプリケーションに変換できます~各ワーカープロセスは同時に HTTP とマイクロサービス通信をサポートします。

サービス層で TCP 通信を確立#

これにより、サービス層で他の Java エンジニアのマイクロサービスに接続できます。たとえば、特定のスクリーンショット機能で処理した base64 を Redis に保存したり、Java サービスを呼び出したりする必要があります。

import { Injectable } from '@nestjs/common';
import { ClientProxy, Transport } from '@nestjs/microservices';
import { firstValueFrom } from 'rxjs';

@Injectable()
export class ScreenshotClient {
  private client: ClientProxy;

  constructor() {
    this.client = new ClientProxy({
      transport: Transport.TCP,
      options: {
        host: process.env.SCREENSHOT_SERVICE_HOST || 'localhost',
        port: parseInt(process.env.SCREENSHOT_SERVICE_PORT || '4000'),
      },
    });
  }

  async generateScreenshot(groups: any) {
    try {
      const result = await firstValueFrom(
        this.client.send({ cmd: 'generate_screenshot' }, groups)
      );
      
      if (!result.success) {
        throw new Error(result.error);
      }
      
      return result.data;
    } catch (error) {
      throw new Error(`スクリーンショット生成に失敗しました: ${error.message}`);
    }
  }
}

client はあなたが接続する IP+port のサービスを表します。

send は、相手のマイクロサービスに送信するメッセージコマンドを示します。

例えば:send ({cmd: 'some_command'}, data)。これで可能です。

もちろん、1 つのサービス内で異なるマイクロサービスを同時に呼び出すこともできます。

@Injectable()
export class SomeService {
  private redisClient: ClientProxy;
  private rabbitClient: ClientProxy;

  constructor() {
    // Redis マイクロサービスクライアント
    this.redisClient = new ClientProxy({
      transport: Transport.REDIS,
      options: {
        host: '192.168.1.111',
        port: 6379,
      },
    });

    // RabbitMQ マイクロサービスクライアント
    this.rabbitClient = new ClientProxy({
      transport: Transport.RMQ,
      options: {
        urls: ['amqp://192.168.1.222:5672'],
        queue: 'my_queue',
      },
    });
  }
}

自分のマイクロサービスを公開#

例えば、Java エンジニアがあるビジネスに対して複数回 DTO-OTO を必要とする場合、私たちのサービスを経由して処理することができます:

import { Controller } from '@nestjs/common';
import { MessagePattern } from '@nestjs/microservices';
import { ScreenshotService } from './screen-shot.service';

@Controller()
export class ScreenshotController {
  constructor(private readonly screenshotService: ScreenshotService) {}

  // これはマイクロサービスエンドポイントです
  @MessagePattern({ cmd: 'generate_screenshot' })
  async generateScreenshot(data: any) {
    try {
      const result = await this.screenshotService.compositeAllGroups(data);
      return {
        success: true,
        data: result
      };
    } catch (error) {
      return {
        success: false,
        error: error.message
      };
    }
  }

  // これは元のHTTPエンドポイントで、変更はありません
  @Post()
  async httpGenerateScreenshot(@Body() data: any) {
    // ... 元のHTTP処理ロジック
  }
}

end----

次回は Prometheus + Grafana の統合による可視化パフォーマンス監視をお届けします。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。