Construindo Microserviços com Nest.js

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.

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *