Introdução: Por que TypeScript é a escolha ideal para microsserviços
A arquitetura distribuída moderna exige do desenvolvedor não apenas conhecimento de frameworks, mas também uma compreensão profunda dos padrões de interação, tratamento de erros e tipagem de dados. TypeScript, graças à sua tipagem estática rigorosa e ao poderoso sistema de decoradores, torna-se o padrão de fato para a construção de microsserviços confiáveis. Ao contrário do JavaScript puro, o TypeScript permite capturar erros em tempo de compilação, o que é crítico para sistemas com dezenas de serviços.
Neste artigo, abordaremos técnicas avançadas de construção de arquitetura de microsserviços em TypeScript: desde a organização de uma estrutura modular baseada em NestJS até a implementação dos padrões transacionais Saga e CQRS. Você aprenderá como configurar uma comunicação eficiente entre serviços via RabbitMQ e gRPC, e obterá modelos de código prontos para soluções de produção.
1. Arquitetura de microsserviços no NestJS: do monolito ao sistema distribuído
NestJS é um framework progressivo para Node.js que é ideal para arquitetura de microsserviços devido ao suporte integrado a transportes e decoradores. Vamos ver como organizar um projeto corretamente.
1.1. Estrutura básica de um microsserviço
Cada microsserviço deve ser um módulo isolado com limites claros. Exemplo de estrutura mínima:
// user-service/src/main.tsimport { 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: { host: '0.0.0.0', port: 3001, }, }, ); await app.listen();}bootstrap();O ponto-chave é o uso de MicroserviceOptions e a tipagem rigorosa do transporte. Isso garante que, ao mudar o protocolo (por exemplo, de TCP para Redis), o compilador indicará quais parâmetros precisam ser alterados.
1.2. Organização modular e Injeção de Dependência
Para sistemas de produção, é importante separar a lógica de negócios do código de infraestrutura. Use módulos do NestJS para agrupar componentes relacionados:
// user-service/src/user/user.module.tsimport { Module } from '@nestjs/common';import { UserController } from './user.controller';import { UserService } from './user.service';import { DatabaseModule } from '../database/database.module';
@Module({ imports: [DatabaseModule], controllers: [UserController], providers: [UserService], exports: [UserService],})export class UserModule {}Uma prática avançada é o uso de provedores de fábrica para configuração dinâmica de clientes de banco de dados ou filas de mensagens.
2. Padrões Saga e CQRS: gerenciamento de transações distribuídas
Na arquitetura de microsserviços, não é possível usar transações ACID tradicionais. Em vez disso, são aplicados os padrões Saga (para consistência de dados) e CQRS (para separação de leitura e escrita).
2.1. Implementação do padrão Saga em TypeScript
Saga é uma sequência de transações locais, onde cada falha aciona uma ação compensatória. Vejamos um exemplo com pedido e pagamento:
// order-service/src/sagas/create-order.saga.tsimport { Saga, ofType } from '@nestjs/cqrs';import { Observable } from 'rxjs';import { delay, map } from 'rxjs/operators';
export class CreateOrderSaga { @Saga() createOrder = (events$: Observable<any>): Observable<ICommand> => { return events$.pipe( ofType(OrderCreatedEvent), delay(1000), map(event => new ReserveInventoryCommand(event.orderId)), ); };
@Saga() handlePaymentFailure = (events$: Observable<any>): Observable<IComma