DEV Community

VivekSinh Rajput
VivekSinh Rajput

Posted on

Microservices in Nest js....

Here's a comprehensive example of a microservices architecture using NestJS where two applications (appA and appB) run on HTTP servers and communicate via microservices using both ClientProxy for requests and MessagePattern for handling responses. This setup will demonstrate how each app can both send and handle messages:

Project Structure

Create a new directory for your project, then:

mkdir nestjs-microservices-example
cd nestjs-microservices-example

# Create appA
nest new appA
cd appA
npm install @nestjs/microservices

# Create appB
cd ../
nest new appB
cd appB
npm install @nestjs/microservices
Enter fullscreen mode Exit fullscreen mode

AppA Configuration

appA/src/main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '@nestjs/microservices';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Set up microservice for appA
  app.connectMicroservice({
    transport: Transport.TCP,
    options: {
      host: 'localhost',
      port: 8888,
    },
  });

  await app.startAllMicroservices();
  await app.listen(3000);
}
bootstrap();
Enter fullscreen mode Exit fullscreen mode

appA/src/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: 'APP_B_SERVICE',
        transport: Transport.TCP,
        options: {
          host: 'localhost',
          port: 8889,
        },
      },
    ]),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

appA/src/app.controller.ts:

import { Controller, Get, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { MessagePattern } from '@nestjs/microservices';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    @Inject('APP_B_SERVICE') private readonly appBClient: ClientProxy,
  ) {}

  @Get()
  async getHello() {
    return this.appBClient.send<string>({ cmd: 'hello' }, 'AppA');
  }

  @MessagePattern({ cmd: 'reply' })
  replyToAppB(data: string): string {
    return `AppA received: ${data}`;
  }
}
Enter fullscreen mode Exit fullscreen mode

appA/src/app.service.ts:

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

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World from AppA!';
  }
}
Enter fullscreen mode Exit fullscreen mode

AppB Configuration

appB/src/main.ts:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport } from '@nestjs/microservices';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);

  // Set up microservice for appB
  app.connectMicroservice({
    transport: Transport.TCP,
    options: {
      host: 'localhost',
      port: 8889,
    },
  });

  await app.startAllMicroservices();
  await app.listen(3001);
}
bootstrap();
Enter fullscreen mode Exit fullscreen mode

appB/src/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: 'APP_A_SERVICE',
        transport: Transport.TCP,
        options: {
          host: 'localhost',
          port: 8888,
        },
      },
    ]),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

appB/src/app.controller.ts:

import { Controller, Get, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { MessagePattern } from '@nestjs/microservices';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(
    private readonly appService: AppService,
    @Inject('APP_A_SERVICE') private readonly appAClient: ClientProxy,
  ) {}

  @Get()
  async getHello() {
    // AppB sends a request to AppA
    return this.appAClient.send<string>({ cmd: 'reply' }, 'Hello from AppB');
  }

  @MessagePattern({ cmd: 'hello' })
  replyToAppA(data: string): string {
    return `AppB received: ${data}`;
  }
}
Enter fullscreen mode Exit fullscreen mode

appB/src/app.service.ts:

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

@Injectable()
export class AppService {
  getHello(): string {
    return 'Hello World from AppB!';
  }
}
Enter fullscreen mode Exit fullscreen mode

Running the Applications

  1. Start AppA:
   cd appA
   npm run start:dev
Enter fullscreen mode Exit fullscreen mode
  1. Start AppB:
   cd ../appB
   npm run start:dev
Enter fullscreen mode Exit fullscreen mode

Now, both applications are running:

  • AppA is listening on port 3000 for HTTP requests and on TCP port 8888 for microservices communication.
  • AppB is listening on port 3001 for HTTP requests and on TCP port 8889 for microservices communication.

  • Visiting localhost:3000 will trigger AppA to send a message to AppB (hello command) and return AppB's response.

  • Visiting localhost:3001 will trigger AppB to send a message to AppA (reply command) and return AppA's response.

This setup demonstrates a complete cycle of microservices communication where both apps can act as clients and servers for each other. Remember, this example assumes both services are on the same machine for simplicity; in a production environment, you'd configure networking appropriately for inter-service communication.

Top comments (0)