gRPC в C#: мощнее REST, но не всегда

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

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

Начать курс

gRPC в C#: когда REST — прошлый век, а HTTP/1.1 — тормоз

Представьте, что вы — пилот Формулы-1. Ваш болид способен разгоняться до 380 км/ч, но вы едете по городским пробкам. Бессмысленно, правда? Примерно так же часто используют gRPC в C# — мощнейший инструмент для межсервисного взаимодействия — там, где хватило бы обычного REST API. А потом удивляются: «почему сложно отлаживать, зачем столько кода?».

Давайте разберёмся, когда использовать gRPC действительно оправдано, а когда лучше остаться на проверенном HTTP/1.1. Спойлер: gRPC — это не серебряная пуля. Это ракетный ускоритель для правильных задач.

Что такое gRPC и почему C# — идеальный полигон

gRPC (Google Remote Procedure Call) — это фреймворк для удалённого вызова процедур, построенный на HTTP/2 и Protocol Buffers. Вместо громоздкого JSON — компактный бинарный формат. Вместо одного запрос-ответ — полноценные стримы, мультиплексирование и двусторонняя связь.

Почему C# gRPC — это бомба? Потому что .NET Core с самого начала затачивали под высоконагруженные микросервисы. Асинхронность, Span<T>, низкий уровень аллокаций — всё это делает связку C# + gRPC одной из самых производительных в индустрии.

// Пример простого .proto файла
syntax = "proto3";

service OrderService {
  rpc GetOrder (OrderRequest) returns (OrderResponse);
  rpc SubscribeOrders (OrderFilter) returns (stream OrderUpdate);
}

message OrderRequest {
  string order_id = 1;
}

message OrderResponse {
  string id = 1;
  double total = 2;
  repeated string items = 3;
}

После генерации кода через protoc или пакет Grpc.Tools вы получите полноценный C# класс, который можно использовать как обычный метод.

Когда gRPC в C# реально нужен? 5 железобетонных сценариев

1. Микросервисы с высокой нагрузкой (1000+ rps)

Если ваша система обрабатывает тысячи запросов в секунду, каждый лишний килобайт в JSON и каждый дополнительный RTT (round-trip time) превращаются в потерю денег. gRPC в C# даёт выигрыш в скорости до 7-10 раз по сравнению с REST/JSON за счёт:

  • Бинарной сериализации (Protobuf — в 3-5 раз компактнее JSON)
  • HTTP/2 мультиплексирования (один TCP-канал на множество запросов)
  • Отсутствия накладных расходов на парсинг заголовков

2. Стриминг данных в реальном времени

Вам нужно передавать котировки акций, логи, телеметрию IoT-датчиков или обновления UI? Streaming gRPC C# — ваш выбор. Поддерживаются четыре типа стримов:

  • Unary — классический запрос-ответ
  • Server streaming — сервер шлёт данные клиенту
  • Client streaming — клиент шлёт пачку данных серверу
  • Bidirectional streaming — двусторонний непрерывный обмен
// Серверная часть bidirectional streaming
public override async Task SubscribeOrders(
    IAsyncStreamReader<OrderFilter> requestStream,
    IServerStreamWriter<OrderUpdate> responseStream,
    ServerCallContext context)
{
    await foreach (var filter in requestStream.ReadAllAsync())
    {
        var update = new OrderUpdate 
        { 
            OrderId = filter.OrderId, 
            Status = "Shipped" 
        };
        await responseStream.WriteAsync(update);
    }
}

3. Внутренние микросервисы одной команды

gRPC плохо подходит для публичных API (слабая поддержка браузеров, сложный дебаг). Но внутри кластера — это идеальный транспорт. Если вы контролируете и клиент, и сервер, gRPC на C# даёт:

  • Строгую типизацию через .proto контракты
  • Автоматическую генерацию клиентов
  • Поддержку graceful shutdown и deadline propagation

4. Мобильные приложения с плохим каналом

Мобильный интернет — это боль: высокий пинг, частые обрывы, маленький bandwidth. gRPC в C# сжимает данные в 4-5 раз сильнее JSON. А HTTP/2 позволяет держать одно соединение, а не открывать новое под каждый запрос. Для мобильных SDK на Xamarin или .NET MAUI — это спасение.

5. Полиглотные системы (C# + Go + Python + ...)

gRPC — кроссплатформенный. Вы пишете .proto файл один раз, а генерируете клиенты на C#, Go, Python, Java, Rust. Это идеально, когда ваш бэкенд на C#, а ML-сервисы на Python. Protobuf C# гарантирует, что структуры данных совпадут на всех языках.

Когда gRPC — это overkill? Спойлер: чаще, чем кажется

Не используйте gRPC в C#, если:

  • Ваш API публичный. Браузеры не поддерживают gRPC напрямую (нужен gRPC-web, который теряет часть преимуществ). REST + JSON — стандарт де-факто для внешних интеграций.
  • У вас 2-3 микросервиса с нагрузкой 50 rps. Настройка gRPC, тулинг, дебаг — овчинка выделки не стоит. Обычный WebAPI на ASP.NET Core справится.
  • Вам нужна человекочитаемость. JSON можно посмотреть в браузере, curl, Postman. Для gRPC нужны gRPCurl, BloomRPC или GUI-клиенты. Это дополнительный барьер.
  • Вы используете legacy .NET Framework. gRPC полноценно поддерживается только на .NET Core 3.1+ и .NET 5+. На старом Framework придётся использовать Grpc.Core (устаревший пакет) с ограничениями.

Практический пример: переписываем REST-метод на gRPC в C#

Допустим, у нас есть метод получения списка заказов пользователя на REST:

// REST API
[HttpGet("users/{userId}/orders")]
public async Task<IActionResult> GetOrders(Guid userId)
{
    var orders = await _db.Orders
        .Where(o => o.UserId == userId)
        .ToListAsync();
    return Ok(orders); // JSON — 12 Kb на 100 заказов
}

Переписываем на gRPC C#:

// .proto файл
service UserService {
  rpc GetUserOrders (UserOrdersRequest) returns (UserOrdersResponse);
}

message UserOrdersRequest {
  string user_id = 1;
  int32 page_size = 2;
  int32 page_token = 3;
}

message UserOrdersResponse {                

Блоги

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