Микросервисы на C#: архитектура и практика от А до Я

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

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

Начать курс

Введение в микросервисы на C#

Микросервисная архитектура (MSA) — это подход к разработке программного обеспечения, при котором приложение строится как набор небольших, независимо развертываемых сервисов. Каждый сервис реализует одну бизнес-возможность, имеет собственную базу данных и может быть написан на разных языках. Однако в экосистеме .NET платформа C# и ASP.NET Core предоставляют одни из лучших инструментов для построения надежных микросервисов.

В этой статье мы рассмотрим полный цикл создания микросервисов на C#: от проектирования архитектуры до развертывания в контейнерах. Вы узнаете, как организовать взаимодействие между сервисами, обеспечить их отказоустойчивость и масштабируемость.

1. Проектирование архитектуры микросервисов на .NET

Первый шаг — правильно разбить монолитное приложение на сервисы. Хорошая практика — следовать принципу Domain-Driven Design (DDD) и выделять Bounded Contexts (ограниченные контексты).

1.1. Определение границ сервисов

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

  • Catalog Service — управление товарами
  • Order Service — обработка заказов
  • Payment Service — платежи
  • Notification Service — уведомления

Важно: каждый сервис владеет своей базой данных. Это предотвращает связность и позволяет независимо масштабировать сервисы.

1.2. Структура проекта ASP.NET Core

Типичный микросервис на C# состоит из нескольких слоев:

  • API Layer — контроллеры и middleware
  • Application Layer — CQRS, MediatR, команды и запросы
  • Domain Layer — сущности, value objects, агрегаты
  • Infrastructure Layer — репозитории, DbContext, внешние сервисы

Пример минимальной структуры каталога:

MyMicroservice/
├── MyMicroservice.Api/
│   └── Controllers/
├── MyMicroservice.Application/
│   └── Commands/
├── MyMicroservice.Domain/
│   └── Entities/
└── MyMicroservice.Infrastructure/
    └── Data/

2. Реализация микросервиса на C#: практический пример

Создадим простой сервис для управления каталогом товаров с использованием ASP.NET Core 8 и Entity Framework Core.

2.1. Настройка WebApplication

В файле Program.cs настраиваем минимальный API:

var builder = WebApplication.CreateBuilder(args);

// Добавляем сервисы
builder.Services.AddDbContext<CatalogDbContext>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("CatalogDb")));

builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(Program).Assembly));

builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();

var app = builder.Build();

// Middleware
if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

// Minimal API endpoint
app.MapGet("/api/products", async (IMediator mediator) =>
{
    var products = await mediator.Send(new GetProductsQuery());
    return Results.Ok(products);
});

app.Run();

2.2. Модель данных и CQRS

Создаем сущность Product:

public class Product
{
    public Guid Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public string Category { get; set; } = string.Empty;
}

Используем паттерн CQRS с MediatR для разделения команд и запросов:

public record GetProductsQuery() : IRequest<List<Product>>;

public class GetProductsHandler : IRequestHandler<GetProductsQuery, List<Product>>
{
    private readonly CatalogDbContext _context;
    
    public GetProductsHandler(CatalogDbContext context)
    {
        _context = context;
    }
    
    public async Task<List<Product>> Handle(GetProductsQuery request, CancellationToken cancellationToken)
    {
        return await _context.Products.ToListAsync(cancellationToken);
    }
}

3. Коммуникация между микросервисами

Существует два основных подхода: синхронный (HTTP/gRPC) и асинхронный (Message Broker). В .NET оба реализованы отлично.

3.1. Синхронное взаимодействие через gRPC

gRPC — современный протокол на HTTP/2 с высокой производительностью. Для C# используем Grpc.AspNetCore:

// Определение сервиса в .proto
service CatalogService {
  rpc GetProduct (ProductRequest) returns (ProductResponse);
}

// Реализация на сервере
public class CatalogService : Catalog.CatalogBase
{
    public override async Task<ProductResponse> GetProduct(ProductRequest request, ServerCallContext context)
    {
        var product = await _dbContext.Products.FindAsync(request.Id);
        return new ProductResponse 
        { 
            Id = product.Id.ToString(),
            Name = product.Name,
            Price = (double)product.Price
        };
    }
}

3.2. Асинхронное взаимодействие через RabbitMQ

Для событийной архитектуры используем RabbitMQ с библиотекой MassTransit:

// Публикация события
public class OrderCreatedHandler : IRequestHandler<CreateOrderCommand, Guid>
{
    private readonly IPublishEndpoint _publishEndpoint;
    
    public async Task<Guid> Handle(CreateOrderCommand request, CancellationToken ct)
    {
        // Сохраняем заказ в БД
        var orderId = Guid.NewGuid();
        await _dbContext.Orders.AddAsync(new Order { Id = orderId, ... });
        await _dbContext.SaveChangesAsync(ct);
        
        // Публикуем событие
        await _publishEndpoint.Publish(new OrderCreatedEvent 
        { 
            OrderId = orderId,
            TotalAmount = request.TotalAmount 
        }, ct);
        
        return orderId;
    }
}

// Подписка в другом сервисе
public class OrderCreatedConsumer : IConsumer<OrderCreatedEvent>
{
    public async Task Consume(ConsumeContext<OrderCreatedEvent> context)
    {
        // Отправляем уведомление, обновляем склад и т.д.
        await _emailService.Send                

Блоги

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