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
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();
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 {}
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}`;
}
}
appA/src/app.service.ts:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World from AppA!';
}
}
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();
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 {}
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}`;
}
}
appB/src/app.service.ts:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World from AppB!';
}
}
Running the Applications
- Start AppA:
cd appA
npm run start:dev
- Start AppB:
cd ../appB
npm run start:dev
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:3000will trigger AppA to send a message to AppB (hellocommand) and return AppB's response.Visiting
localhost:3001will trigger AppB to send a message to AppA (replycommand) 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)