Construindo Microserviços com Nest.js
Com o aumento da complexidade das aplicações modernas, os desenvolvedores têm procurado arquiteturas que permitam uma maior escalabilidade e manutenção do código. Uma dessas arquiteturas é a de microserviços, que divide uma aplicação em pequenos serviços independentes que podem ser desenvolvidos, implantados e escalados separadamente. Nest.js, um framework de Node.js inspirado no Angular, oferece suporte robusto para a construção de microserviços. Neste artigo, vamos explorar como construir microserviços com Nest.js, desde a configuração inicial até a comunicação entre serviços e a implementação de melhores práticas.
Pré-requisitos
Antes de começarmos, é importante garantir que você tenha os seguintes pré-requisitos:
- Conhecimento básico de JavaScript/TypeScript.
- Experiência com Node.js e Nest.js.
- Entendimento dos conceitos de microserviços.
- Node.js instalado em sua máquina.
Com isso em mente, vamos iniciar nosso projeto de microserviços com Nest.js.
Configurando o Projeto
Instalando o Nest CLI
Primeiro, vamos instalar o Nest CLI, que facilitará a criação e gerenciamento de nosso projeto Nest.js.
npm install -g @nestjs/cli
Criando um Novo Projeto
Agora, criaremos um novo projeto Nest.js chamado microservices-demo
.
nest new microservices-demo
Estrutura do Projeto
A estrutura inicial do projeto terá a seguinte aparência:
microservices-demo/
├── src/
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test/
├── .eslintrc.js
├── .prettierrc
├── nest-cli.json
├── package.json
├── tsconfig.build.json
└── tsconfig.json
Criando Módulos de Microserviços
Vamos criar dois microserviços simples: um serviço de usuários (users-service
) e um serviço de autenticação (auth-service
).
Serviço de Usuários
Criando o Módulo
Primeiro, criamos o módulo para o serviço de usuários.
nest generate module users
nest generate service users
nest generate controller users
Implementando o Serviço de Usuários
No arquivo src/users/users.service.ts
, vamos definir algumas operações básicas:
import { Injectable } from '@nestjs/common';
@Injectable()
export class UsersService {
private readonly users = [
{ id: 1, name: 'John Doe', email: 'john@example.com' },
{ id: 2, name: 'Jane Doe', email: 'jane@example.com' },
];
findAll() {
return this.users;
}
findOne(id: number) {
return this.users.find(user => user.id === id);
}
}
Implementando o Controlador
No arquivo src/users/users.controller.ts
, vamos criar rotas para acessar o serviço de usuários:
import { Controller, Get, Param } from '@nestjs/common';
import { UsersService } from './users.service';
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
findAll() {
return this.usersService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.usersService.findOne(Number(id));
}
}
Serviço de Autenticação
Criando o Módulo
Agora, criamos o módulo para o serviço de autenticação.
nest generate module auth
nest generate service auth
nest generate controller auth
Implementando o Serviço de Autenticação
No arquivo src/auth/auth.service.ts
, vamos definir operações básicas de autenticação:
import { Injectable } from '@nestjs/common';
@Injectable()
export class AuthService {
validateUser(username: string, pass: string): any {
// Lógica de validação de usuário
if (username === 'john' && pass === 'changeme') {
return { userId: 1, username: 'john' };
}
return null;
}
}
Implementando o Controlador
No arquivo src/auth/auth.controller.ts
, vamos criar rotas para acessar o serviço de autenticação:
import { Controller, Post, Body } from '@nestjs/common';
import { AuthService } from './auth.service';
@Controller('auth')
export class AuthController {
constructor(private readonly authService: AuthService) {}
@Post('login')
login(@Body() body: { username: string, password: string }) {
return this.authService.validateUser(body.username, body.password);
}
}
Comunicação entre Microserviços
Nest.js facilita a comunicação entre microserviços utilizando diferentes transportadores (transporters), como TCP, Redis, NATS e outros. Para este exemplo, usaremos a comunicação baseada em TCP.
Configurando a Comunicação TCP
Serviço de Usuários
No arquivo src/main.ts
, configuramos o serviço de usuários para ouvir em uma porta TCP:
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AppModule, {
transport: Transport.TCP,
options: {
port: 3001,
},
});
await app.listen();
}
bootstrap();
Serviço de Autenticação
No arquivo src/main.ts
, configuramos o serviço de autenticação para se comunicar com o serviço de usuários:
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { Transport, MicroserviceOptions } from '@nestjs/microservices';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.connectMicroservice<MicroserviceOptions>({
transport: Transport.TCP,
options: {
host: 'localhost',
port: 3002,
},
});
await app.startAllMicroservicesAsync();
await app.listen(3000);
}
bootstrap();
Chamando o Serviço de Usuários
No serviço de autenticação, podemos agora chamar o serviço de usuários para validar um usuário:
import { Injectable, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
@Injectable()
export class AuthService {
constructor(@Inject('USERS_SERVICE') private readonly client: ClientProxy) {}
async validateUser(username: string, pass: string): Promise<any> {
const user = await this.client.send({ cmd: 'get-user' }, { username }).toPromise();
if (user && user.password === pass) {
return user;
}
return null;
}
}
E configuramos o cliente no módulo de autenticação (src/auth/auth.module.ts
):
import { Module } from '@nestjs/common';
import { ClientsModule, Transport } from '@nestjs/microservices';
import { AuthService } from './auth.service';
import { AuthController } from './auth.controller';
@Module({
imports: [
ClientsModule.register([
{ name: 'USERS_SERVICE', transport: Transport.TCP, options: { port: 3001 } },
]),
],
providers: [AuthService],
controllers: [AuthController],
})
export class AuthModule {}
Conclusão
Construir microserviços com Nest.js permite criar aplicações escaláveis e organizadas, utilizando uma arquitetura modular e robusta. Com suporte para diferentes transportadores de comunicação e uma estrutura inspirada em Angular, o Nest.js facilita o desenvolvimento de microserviços que são fáceis de manter e expandir. Esperamos que este guia tenha fornecido uma visão clara de como começar a construir microserviços com Nest.js e que você esteja pronto para aplicar esses conceitos em seus próprios projetos.