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: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)