Микросервисы на TypeScript: архитектура и практика

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: Почему TypeScript идеален для микросервисов

Микросервисная архитектура стала стандартом для построения сложных, масштабируемых и отказоустойчивых приложений. TypeScript, благодаря строгой типизации, богатой экосистеме и поддержке асинхронности, является одним из лучших языков для реализации микросервисов. Он позволяет писать код, который легче рефакторить, тестировать и документировать, что критически важно при разделении системы на десятки независимых сервисов.

В этой статье мы разберём архитектурные принципы, построим простой микросервис на NestJS, настроим межсервисное взаимодействие через RabbitMQ и упакуем всё в Docker Compose. Вы получите готовую практическую основу для старта.

Архитектура микросервисов на TypeScript

Правильная архитектура — залог успеха. Для TypeScript-микросервисов выделяют три ключевых слоя:

  • Транспортный слой — отвечает за приём и отправку запросов (HTTP, gRPC, очереди сообщений).
  • Бизнес-логика — чистые функции и сервисы, не зависящие от фреймворка.
  • Слой данных — репозитории и ORM (TypeORM, Prisma).

Каждый микросервис должен быть автономным: иметь свою базу данных, CI/CD и логику развёртывания. Связь между сервисами обычно реализуется через асинхронные очереди (RabbitMQ, Kafka) или синхронные вызовы (gRPC).

Практика: Создание микросервиса на NestJS

Шаг 1: Инициализация проекта

Установите NestJS CLI и создайте новый проект:

npm i -g @nestjs/cli
nest new user-service --package-manager npm
cd user-service

Шаг 2: Добавление поддержки микросервисов

NestJS имеет встроенную поддержку микросервисных транспортёров. Установим RabbitMQ:

npm install @nestjs/microservices amqplib amqp-connection-manager

Создадим main.ts, который запускает сервис как микросервис:

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.RMQ,
      options: {
        urls: ['amqp://localhost:5672'],
        queue: 'user_queue',
        queueOptions: { durable: false },
      },
    },
  );
  await app.listen();
}
bootstrap();

Шаг 3: Реализация контроллера

Создадим простой контроллер, который обрабатывает сообщения из очереди:

import { Controller } from '@nestjs/common';
import { MessagePattern, Payload } from '@nestjs/microservices';

@Controller()
export class UserController {
  @MessagePattern('user.create')
  createUser(@Payload() data: { name: string; email: string }): string {
    // Здесь должна быть бизнес-логика создания пользователя
    return `Пользователь ${data.name} создан`;
  }
}

Теперь любой сервис может отправить сообщение в очередь user_queue с паттерном user.create и получить ответ.

Межсервисное взаимодействие: синхронное и асинхронное

Синхронное: gRPC

Для высоконагруженных систем, где требуется строгая типизация и низкая задержка, используйте gRPC. Установите пакет:

npm install @nestjs/microservices @grpc/grpc-js @grpc/proto-loader

Определите .proto файл:

syntax = "proto3";
package user;
service UserService {
  rpc GetUser (UserId) returns (User);
}
message UserId { int32 id = 1; }
message User { string name = 1; string email = 2; }

В контроллере используйте декоратор @GrpcMethod для обработки запроса.

Асинхронное: RabbitMQ

Мы уже показали пример с RabbitMQ. Добавим клиентскую часть для отправки сообщений из другого сервиса:

import { ClientProxy, ClientProxyFactory, Transport } from '@nestjs/microservices';

// В сервисе-отправителе
const client: ClientProxy = ClientProxyFactory.create({
  transport: Transport.RMQ,
  options: { urls: ['amqp://localhost:5672'], queue: 'user_queue' },
});

// Отправка сообщения и получение ответа
const result = await client.send('user.create', { name: 'Иван', email: 'ivan@mail.ru' }).toPromise();
console.log(result); // "Пользователь Иван создан"

Развёртывание: Docker Compose для микросервисов

Для оркестрации нескольких сервисов используйте docker-compose.yml. Пример конфигурации для двух микросервисов и RabbitMQ:

version: '3.8'
services:
  rabbitmq:
    image: rabbitmq:3-management
    ports:
      - "5672:5672"
      - "15672:15672"

  user-service:
    build: ./user-service
    ports:
      - "3001:3000"
    environment:
      - RABBITMQ_URL=amqp://rabbitmq:5672
    depends_on:
      - rabbitmq

  order-service:
    build: ./order-service
    ports:
      - "3002:3000"
    environment:
      - RABBITMQ_URL=amqp://rabbitmq:5672
    depends_on:
      - rabbitmq

Запустите всё одной командой:

docker-compose up --build

Каждый сервис будет запущен в изолированном контейнере, но сможет общаться через RabbitMQ.

Заключение

TypeScript предоставляет мощный инструментарий для создания микросервисов: от строгой типизации до готовых решений вроде NestJS. Мы рассмотрели ключевые архитектурные принципы, реализовали асинхронное взаимодействие через RabbitMQ и синхронное через gRPC, а также настроили контейнеризацию с Docker Compose.

Для углублённого изучения рекомендуем обратить внимание на паттерны Saga (для распределённых транзакций), CQRS и интеграцию с Kubernetes.

Блоги

Рекомендаций по книгам