Микросервисы на C#: архитектура и практика для .NET разработчиков

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

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

Начать курс

Микросервисы на C#: от теории к практике на .NET

Микросервисная архитектура стала стандартом для построения масштабируемых и отказоустойчивых приложений. Платформа .NET (C#) предоставляет все необходимые инструменты для создания таких систем: от встроенной поддержки контейнеризации до мощных фреймворков для межсервисного взаимодействия. В этой статье мы разберем ключевые принципы построения микросервисов на C# и рассмотрим практические примеры кода.

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

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

Ключевые принципы для .NET разработчика:

  • Единая ответственность (Single Responsibility) — каждый микросервис решает одну задачу.
  • Независимость данных — каждый сервис имеет свою базу данных (Database per Service).
  • Слабая связность (Loose Coupling) — сервисы общаются через API, а не через общую память.
  • Автономность — сервис может быть изменен и переразвернут без остановки всей системы.

Для создания нового проекта микросервиса на C# используйте команду:

dotnet new webapi -n UserService
dotnet new webapi -n OrderService
dotnet new webapi -n NotificationService

Каждый проект получает свой Program.cs, конфигурации и зависимости.

2. Межсервисное взаимодействие: REST и gRPC

В .NET есть два основных подхода к общению между микросервисами: синхронный (REST/gRPC) и асинхронный (через брокеры сообщений). Рассмотрим оба.

REST API с использованием HttpClient

Самый простой способ — использовать HttpClientFactory для создания типизированного клиента.

// В Program.cs сервиса OrderService
builder.Services.AddHttpClient<IUserServiceClient, UserServiceClient>(client =>
{
    client.BaseAddress = new Uri("http://userservice:5000");
});

// UserServiceClient.cs
public class UserServiceClient : IUserServiceClient
{
    private readonly HttpClient _httpClient;

    public UserServiceClient(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<UserDto> GetUserAsync(int userId)
    {
        var response = await _httpClient.GetAsync($"/api/users/{userId}");
        response.EnsureSuccessStatusCode();
        return await response.Content.ReadFromJsonAsync<UserDto>();
    }
}

Рекомендация: используйте Polly (библиотека для .NET) для реализации политик повторных попыток и Circuit Breaker.

gRPC для высокопроизводительных сценариев

gRPC работает поверх HTTP/2 и использует Protocol Buffers для сериализации. Это значительно быстрее JSON.

// Определение сервиса в user.proto
service UserGrpcService {
  rpc GetUser (GetUserRequest) returns (UserResponse);
}

// Код сервера на C#
public class UserGrpcServiceImpl : UserGrpcService.UserGrpcServiceBase
{
    public override Task<UserResponse> GetUser(GetUserRequest request, ServerCallContext context)
    {
        var user = _dbContext.Users.Find(request.UserId);
        return Task.FromResult(new UserResponse 
        { 
            Id = user.Id, 
            Name = user.Name, 
            Email = user.Email 
        });
    }
}

3. Управление данными и транзакциями

В микросервисах каждая база данных принадлежит только одному сервису. Это исключает прямые SQL-запросы между сервисами. Для работы с данными в .NET стандартом является Entity Framework Core.

Пример конфигурации DbContext для микросервиса

public class OrderDbContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<OrderItem> OrderItems { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>(entity =>
        {
            entity.HasKey(o => o.Id);
            entity.Property(o => o.Status).HasMaxLength(50);
        });
    }
}

// В Program.cs
builder.Services.AddDbContext<OrderDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("OrderDb")));

Важно: для обеспечения согласованности данных между сервисами используйте сагу (Saga) — паттерн для управления распределенными транзакциями. Пример реализации на C# с использованием MassTransit:

public class OrderSaga : MassTransitStateMachine<OrderSagaState>
{
    public State Submitted { get; set; }
    public State PaymentApproved { get; set; }
    public State Completed { get; set; }

    public Event<OrderSubmitted> OrderSubmitted { get; set; }
    public Event<PaymentProcessed> PaymentProcessed { get; set; }

    public OrderSaga()
    {
        Initially(
            When(OrderSubmitted)
                .Then(context => context.Saga.OrderId = context.Message.OrderId)
                .TransitionTo(Submitted)
                .Publish(context => new ProcessPayment(context.Message.OrderId))
        );

        During(Submitted,
            When(PaymentProcessed)
                .Then(context => context.Saga.PaymentId = context.Message.PaymentId)
                .TransitionTo(PaymentApproved)
                .Publish(context => new CompleteOrder(context.Message.OrderId))
        );
    }
}

4. Развертывание и мониторинг микросервисов

Современные микросервисы на C# обычно разворачиваются в Docker-контейнерах. Вот минимальный Dockerfile для .NET микросервиса:

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["UserService/UserService.csproj", "UserService/"]
RUN dotnet restore "UserService/UserService.csproj"
COPY . .
WORKDIR "/src/UserService"
RUN dotnet build "UserService.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "UserService.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "UserService.dll"]

Для оркестрации используйте Kubernetes или <

Блоги

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