Фреймворк gRPC: как он упрощает задачи разработчика и почему лучше, чем REST API

Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті.

Привет! Я — Роман Махнык, .NET developer в NIX. За моими плечами более трех лет участия в коммерческих проектах. На данный момент занимаюсь проектированием и разработкой веб-приложений с применением облачных технологий.

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

Данный материал будет интересен как джунам, которые только знакомятся с API, так и более опытным специалистам, которые еще не успели поработать с gRPC.

Что объединяет Netflix, Docker, Spotify и Dropbox? То, что все они перешли в организации работы своих микросервисов на gRPC. Этот фреймворк компания Google презентовала в 2015 году. Несмотря на столь юный возраст, gRPC уже подвинул во многих крупных сервисах популярнейший REST API. Но сможет ли он вовсе заменить его? Чтобы ответить на этот вопрос, давайте сравним фреймворки. А также поговорим о балансировке нагрузки, мультиплексировании и HTTP/2. Кроме того, в конце статьи мы создадим простое gRPC-приложение

Почему все уходят от монолитов

Как и у других фреймворков для API, задача gRPC — установить корректное, стабильное, быстрое и безопасное общение между сервисами. В нашем случае это небольшие веб-приложения, которые объединены в единую систему. Каждый из них несет ответственность за отдельную часть работы приложения. В качестве примера представим онлайн-магазин игр, где есть три таких сервиса. Один отвечает за предоставление игр для продажи, второй — за демонстрацию на экране достижений игрока, а третий — за генерацию скидок. Каждая из этих задач требует постоянного обращения к определенному сервису. Почему бы не сделать все это одним приложением с несколькими или даже общей базой данных? Именно в этом суть микросервисного подхода в построении архитектуры приложений.

Причин ухода от монолитов достаточно. Самые весомые такие:

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

Также можем поместить их на облачных сервисах, например, на AWS Lambda и Azure Function. При необходимости они автоматически масштабируются, а оплата производится за количество отработанного времени. В некоторых ситуациях это очень выгодный подход, но он требует особой архитектуры, под которую как раз и подходят микросервисы. Для монолита же придется арендовать как минимум целую виртуальную машину, где оплата будет фиксированной. Это также относится и к вопросу обслуживания. AWS Lambda и Azure Function обслуживаются Amazon и Microsoft соответственно, а за виртуалками придется следить нам.

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

Тестирование. В монолите все части приложения находятся в одном месте. Чтобы протестировать их, придется запускать все. В микросервисном приложении мы можем проверять отработку контрактов для каждого из них, не обращая внимания на остальную часть системы.

С переходом на микросервисы в проекте появляется такая особенность, как распределение ответственности. Мы же не хотим, чтобы сервисы выполняли одну и ту же задачу по несколько раз, верно? Также нелогично постоянно дублировать код и писать функционал, который уже создан. Потому нам надо настроить каналы коммуникации между сервисами. Это можно сделать двумя способами:

  • Синхронное общение — один сервис дожидается ответа от другого.
  • Асинхронное общение — первый сервис кладет сообщение в очередь, второй — по возможности подбирает его, обрабатывает и выдает ответ.

Каждый из вариантов имеет свои преимущества, лучше работает в определенных условиях и при конкретных задачах, но может значительно проигрывать второму способу при других обстоятельствах. В этой статье мы остановимся на технологии синхронного общения. Двумя самыми популярными способами реализации такого общения являются REST и RPC.

В чем разница между REST и gRPC

Чтобы лучше понять принципиальную разницу между этими фреймворками, рассмотрим, как они устроены. Для работы REST посредством самого обычного CRUD подхода обычно используется пять типов HTTP-запросов для данных какого-то ресурса:

  • GET: получение/чтение;
  • POST: добавление/запись;
  • PUT/PATCH: обновление/изменение;
  • DELETE: удаление.

Модель сетевого взаимодействия выглядит так: клиент и сервер объединены общей сетью, в нужный момент клиент отправляет HTTP-запрос, сервер обрабатывает его и возвращает HTTP-ответ. Пока сервер делает свое дело, клиент выделяет дополнительный поток, в котором и происходит ожидание.

Если поменять HTTP-запросы на RPC-коллы (вызовы удаленных процедур), то мы получаем схожую схему. Разница заключается в том, как происходят отправка и получение сервером запроса и получение ответа клиентом.

RPC — это протокол вызова удаленных процедур, который одна программа может использовать, чтобы вызвать метод, функцию или процедуру в другой, доступной в сети. При этом не нужно досконально разбираться в сети. Как видим на схеме, у клиента и сервера есть дополнительный уровень в общении — клиентская и серверная заглушки. Они созданы для того, чтобы отправлять данные по нужному адресу. Соответственно, в самом коде мы об этом вообще не переживаем. Эти заглушки генерируются автоматически. Все, что нам остается сделать — вызвать нужную процедуру.

Новая и, пожалуй, наиболее действенная и перспективная реализация этой концепции — фреймворк gRPC. По сравнению с другими реализациями RPC, у него есть множество преимуществ:

  • Идиоматические клиентские библиотеки на более чем 10 языках. Мы можем использовать библиотеки на Java, C#, JavaScript, Python и т.д. Все это выглядит нативно — не так, словно мы используем какую-то инопланетную технологию.
  • Простая структура определения сервисов. Для этого используются .proto-файлы.
  • HTTP/2. Двунаправленная потоковая передача на основе HTTP/2
  • Трассировка. Позволяет мониторить вызовы процедур, что очень полезно для отладки приложения и анализа работы сервисов для их дальнейших оптимизаций и улучшений.
  • Health check. С помощью этого механизма можно быстро проверить, работоспособен ли сервис и готов ли он обрабатывать запросы. Это помогает для балансировки нагрузки.
  • Балансировка нагрузки. Эта особенность позволяет распределять нагрузку на несколько экземпляров серверного приложения, тем самым значительно упрощая вопрос масштабирования. Балансировка может производиться как на клиентской части (например, клиентское приложение поочередно отправляет запросы на разные серверы), так и на промежуточной (специальной прокси) посредством сервис-меша.
  • Подключение аутентификации. Ее отсутствие было главным недостатком прошлых реализаций протокола. Из-за такой уязвимости RPC рекомендовали только для внутреннего общения.

Сравнивая гугловскую технологию с REST, здесь тоже находим свои плюсы:

  • Работа с Protobuf. В REST для передачи данных применяется текстовый формат JSON, который не сжимается. Protobuf — это бинарный формат. Используя его, мы избегаем передачи лишних данных и нам не надо будет десериализовать после этого полученные сообщения.
  • Обработка HTTP-запросов. В случае с REST необходимо постоянно думать, какой статус-код может прийти, какие данные будут храниться и т.п. В gRPC мы прикладываем минимум усилий для вызова удаленных процедур и их определения.
  • Простота определения контрактов. В REST для описания интерфейсов и документации нужно использовать сторонние инструменты и библиотеки — такие, как OpenAPI или Swagger. В gRPC происходит простое определение контрактов в .proto-файлах.
  • HTTP/2. REST зачастую использует более старую версию данного протокола — HTTP/1.1.

Чем хорош HTTP/2? Среди важных преимуществ:

  • бинарный формат передачи данных (уменьшает размер сообщений и ускоряет работу);
  • экономия трафика (усовершенствованное сжатие HTTP-сообщений, в первую очередь хедеров);
  • возможность передавать потоки данных;
  • мультиплексирование (в HTTP 1.1 для передачи трех файлов надо установить три соединения, в каждом из которых будет запрашиваться и отправляться определенный файл. В HTTP/2 можно все передать по одному соединению);
  • приоритезация потоков.

Настройка соединения по gRPC

Последовательность создания gRPC канала включает несколько этапов:

  1. Открытие сокетов.
  2. Установка TCP-соединения.
  3. Согласование TLS.
  4. Запуск HTTP/2-соединения.
  5. Выполнение вызова gRPC-процедуры.

Мы могли бы избежать первых четырех пунктов за счет того, что один раз устанавливаем соединение и просто пользуемся им — это называется Persistent Connection. Почему бы не работать с таким решением постоянно? Однако возникает вопрос, как настроить балансировку нагрузки, когда, допустим, нам понадобится несколько экземпляров сервиса — как их распределять? Вариантов несколько:

  • Балансировка нагрузки на стороне клиента. В этом случае клиентская библиотека знает о существовании нескольких инстансов данного сервиса. Например, она будет отправлять запросы на каждый из них в процентном соотношении.
  • Балансировка нагрузки через прокси. Если эти сервисы хостятся на каком-то оркестраторе (типа Kubernetes), он может решить, что инстансов слишком много, и убирает один или, наоборот, добавляет новый. В этом случае помогает балансировка нагрузки через прокси Service Mesh. Это может быть Linkerd, Istio, Consul и т.п. Клиент будет устанавливать одно постоянное соединение к Mesh, а уже он посмотрит, какие есть экземпляры сервиса, когда они появляются или исчезают и будет хендлить это. Соединение будет только к актуальным сервисам, а клиент об этом знать не будет — у него всегда один коннекшн.

Иногда gRPC сравнивают с WCF. Я не думаю, что это актуально, поскольку gRPC — это узконаправленный фреймворк, который хорошо решает одну задачу. WCF — более универсальный фреймворк, который поддерживает RPC, но также поддерживает REST, SOAP и т.п. К сожалению, WCF не является универсальным в плане поддерживаемых платформ, ведь пока он сильно привязан к .NET. В свою очередь gRPC может работать в любой среде, и писать его можно на любых языках из списка поддерживаемых.

Однако на данный момент gRPC не может полноценно функционировать в браузерах. Реализовать HTTP/2-общение в браузере невозможно, потому что нет такого контроля над каналом связи, какой может быть, допустим, в .NET-приложении. Поэтому Google предлагает альтернативу: использовать gRPC-прокси. То есть сам браузер будет отправлять запросы HTTP 1.1 на прокси, который будет мапить сообщение в вызов gRPC процедуры.

На картинке выше вы можете увидеть пример того, как огромное количество микросервисов Netflix таким образом связаны друг с другом — здесь их более 500! Это одна из тех компаний, которая выиграла от перехода на протокол gRPC и усилила производительность своих сервисов. Раньше им для каждого запроса приходилось устанавливать отдельное соединение. Это занимало миллисекунды, но в масштабах такой компании простой на сотнях коннекшенов постепенно складывается в секунды и минуты. Теперь же по одному соединению можно отправлять все запросы. Скорость передачи данных выросла в разы, ведь удается избежать тех самых первых четырех этапов установки соединения.

Создаем приложение gRPC

А теперь обещанный бонус — попробуем создать простое приложение Hello gRPC.

В первую очередь отмечу, что Visual Studio уже имеет предустановленный темплейт для создания подобных сервисов. Нам достаточно зайти в «Создание нового проекта», написать «gRPC» — и перед нами появится шаблон дефолтного gRPC-приложения. При этом поддерживается две самые актуальные версии .NET: 5 и 3.1.

У нас есть .proto-файл, в котором описан сервис и интерфейс. Мы видим, что у этого сервиса есть некая процедура SayHello, которая принимает объект Hello в реквест, описанный ниже, и возвращает в реплай, который в этом же файле и описывается. Уникальной опцией для .NET является csharp_namespace — необходимый для того, чтобы указать, куда генерировать те классы, которые будут использоваться в этом приложении.

syntax = "proto3";

option csharp_namespace = "GrpcExample";

package greet;

// The greeting service definition.
service Greeter {
  // Sends a greeting
  rpc SayHello (HelloRequest) returns (HelloReply);
}

// The request message containing the user's name.
message HelloRequest {
  string name = 1;
}

// The response message containing the greetings.
message HelloReply {
  string message = 1;
}

Под каждым свойством отправляемых и получаемых сообщений есть нумерация свойств. Это нужно для понимания, в каком порядке будут передаваться данные (так как у нас все-таки бинарный формат), а также для поддержки предыдущих версий. Если на сервере мы обновили наш .proto-файл и добавили новое свойство или убрали старое, то клиент, на котором еще не успели обновить файл, просто проигнорирует новое свойство и будет читать старое — как пустое, которое удалили. Соответственно, не будет никаких ошибок.

Теперь рассмотрим регистрацию сервисов gRPC в .NET-приложении. Для этого понадобится одна строчка, которая добавит все необходимые сервисы к нам в проект.

public void ConfigureServices(IServiceCollection services)
{
	services.AddGrpc();
}

Чуть ниже мы видим, что gRPC-сервисы мапятся точно так же, как и обычные контроллеры. Потому есть уже готовый Gtreeter-сервис, интерфейс которого определен в .proto-файле. Если мы попытаемся посмотреть код этого GreeterService, то увидим, что дефолтная реализация уже есть. Сам сервис наследуется от некого GreeterBase — и это как раз тот файл, в который генерируется различная информация и классы, связанные с отправкой и получением сообщений. Все, что мы делаем — наследуемся от этого уже созданного объекта и реализовываем функции так, как нам надо.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapGrpcService<GreeterService>();

        endpoints.MapGet("/", async context =>
        {
            await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client.");
        });
    });
}

Что касается создания клиента под данный сервис, я предлагаю перейти к уже созданному. Здесь мы видим, что клиент WebApi — приложение, которое будет принимать HTTP-запросы и обращаться к gRPC сервису для выполнения на нем процедуры. Все, что поменялось в .proto-файле — namespace, в который будет генерироваться клиентский код.

syntax = "proto3";

option csharp_namespace = "WebApi";

package greet;

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}

В самом проекте Protobuf-файлы регистрируются отдельно. То есть не как обычный файл, а указывается, что будет использоваться конкретный Protobuf и роль данного сервиса в этом контракте. В данном случае, роль будет клиентская. При этом в серверном проекте мы указываем, что используется такой же .proto-файл, но роль — сервер.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <Protobuf Include="Protos\greet.proto" GrpcServices="Client" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Grpc.AspNetCore" Version="2.39.0" />
    <PackageReference Include="Grpc.Net.ClientFactory" Version="2.39.0" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.6.3" />
  </ItemGroup>

</Project>

Для того, чтобы переиспользовать одно и то же соединение, мы регистрируем фабрику gRPC клиентов. Делается это просто: приводим AddGrpcClient, указываем, какому именно сервису клиент нужен, и добавляем адрес, по которому будет хоститься уже сам сервис (не этот, а gRPC сервер; клиент будет отдельно).

public void ConfigureServices(IServiceCollection services)
{
    services.AddGrpcClient<Greeter.GreeterClient>(o =>
    {
        o.Address = new Uri("https://localhost:5001");
    });

    services.AddControllers();
    services.AddSwaggerGen(c =>
    {
        c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApi", Version = "v1" });
    });
}

Теперь давайте попробуем использовать наш gRPC клиент. Мы можем в любой момент вытащить его в нужном нам объекте через Dependency Injection. После чего — обращаться к нему как к обычному объекту. В нашем случае я сделал SayHello эндпоинт. Это функция контроллера, поэтому принимать она будет запросы HTTP и для обработки будет обращаться уже к gRPC сервису.

[ApiController]
[Route("[controller]")]
public class GreetController : ControllerBase
{
    private readonly Greeter.GreeterClient _client;

    public GreetController(Greeter.GreeterClient client)
    {
        _client = client;
    }

    [HttpPost]
    public async Task<IActionResult> SayHello([FromBody]HelloRequest request)
    {
        var result = await _client.SayHelloAsync(request);
        var result2 = await _client.SayHelloAsync(request);
        var result3 = await _client.SayHelloAsync(request);

        return Ok(new { MessageSum = result.Message + result2.Message + result3.Message });
    }
}

Далее запускаем gRPC сервис, убеждаемся, что он функционирует, и запускаем клиент.

С помощью Swagger сделаем отправку этого запроса, чтобы немного облегчить процедуру. И укажем какое-то имя как аргумент. gRPC сервис увидел вызов данной процедуры, обработал его, залоггировал, и в ответе мы получили ожидаемый результат — и на этом, собственно, все.

Сейчас уже немало проектов использует gRPC, хотя, к сожалению, коммьюнити его поклонников пока не такое большое, как у REST API. Технология относительно новая, и многие пока не привыкли к ней. Но я уверен: с таким быстрым ростом популярности gRPC в последнее время сообщество разработчиков будет развиваться более активно. Ведь, как вы могли убедиться, gRPC действительно дает множество плюсов в решении сложных задач.

👍НравитсяПонравилось12
В избранноеВ избранном7
LinkedIn
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Допустимые теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter

Очередная битва «микросервисы и монолит». Вы ж с переходом на микросервисы учли проблему distributed transaction и дописали логику отката вызовов с переходом на микросервисы с жирного монолита? Паттерн saga применили или когда что-то упадет, будет бо-бо с ручной правкой базы на проде?

Дык когда все через RPC то это называется «распределенный монолит» а не «микросервисы». Оно и тормозить будет из-за постоянного дерганья сети, и если один кусок грохнется — то эффект домино с отказами. То есть, преимуществ перед монолитом толком нет, а проблемы и тормоза — вот они!

Сейчас уже немало проектов использует gRPC, хотя, к сожалению, коммьюнити его поклонников пока не такое большое, как у REST API

В последнее время пожалуй ни одного нового проекта не попадётся, где общение между сервисами внутри не по gRPC. Его ещё на веб-клиент лепить пытаются.

Помолимся, чтоб взлетело и отправило на тот свет все эти конченые приколы по именованию урлов, использованию методов и кодов.

Если вопрос только в том, как микросервисное спагетти общается между собой горизонтально, то самое важное в этом всём — оба варианта синхронные, поэтому с точки зрения именно архитектуры разницы особо-то и нет...

Если рассматривать с точки архитектуры то в плане nfr есть отличия, но на диаграмме — согласен.

Якщо не хочете protobuf, юзайте XDR. (en.wikipedia.org/...​ernal_Data_Representation) Перевірено поколіннями, і, як бонус, легко можно декодувати очима з hexdump’а в процессі дебага — перевірено на собі років 15 тому :)

За моими плечами более трех лет участия в коммерческих проектах

не пиши так, к новичкам очень скептично относятся

WCF не является универсальным в плане поддерживаемых платформ, ведь пока он сильно привязан к .NET.

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

комьюнити пишет порт и вполне может оказаться что через пару лет вцф вернётся в мир дотнета, заменив и вебапи, и жрпц как более полноценная технология

Какой же несусветный бред нычне можно прочитать на доу. Технология построенная вокруг windows транспорт протоколов, xml application level протоколов преимущественно ориентированная на ws-* (soap) соответсвенно вместо открытых смежных market standart техноллгий типа oath будет ориентированная на поддержку всраного samla, не имеющая интеграций ни с одним из современных фронт-енд реверс проксей кроме iis, имеющая устаревшую программную модель, не имеющая интеграций со стороны third party lib под новый фреймворк, не поддерживающая апдейтов http протокола, внезапно при каком-то стечении обстоятельств может быть начата использована в нынешнем вебе. Если таки надо SOAP можно подкинуть в asp.net core service.component model и прокинуть соответсвующий эндпоинт с метаданными чем возится с wcf.

Какой же несусветный бред нычне можно прочитать на доу

вот тут согласен полностью

Технология построенная вокруг windows транспорт протоколов, xml application level протоколов преимущественно ориентированная на ws-* (soap)

что за виндовс транспорт протоколы? L4 и L7 у него из коробки, расширить можно на L3, L5, L6, за L1 и L2 не уверен. Никакой ориентации на соап у него нет, есть лишь дефолтные байндинги под соап, но пользоваться ими не обязательно, я в свое время писал байндинг чтобы он протобафом общался, чтобы жаваскрипи с сайта мог напрямую с вцф сервисом общаться, рест и прочие недефолтные

не имеющая интеграций ни с одним из современных фронт-енд реверс проксей кроме iis

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

не имеющая интеграций со стороны third party lib под новый фреймворк, не поддерживающая апдейтов http протокола

ну такое, обвинять технологию которую забросили на 5+ лет в том что нет интеграций с современными либами... Надо будет добавят

внезапно при каком-то стечении обстоятельств может быть начата использована в нынешнем вебе

у тебя неправильное мнение насчёт него, он как дотнер кор, каркас с мусорным наполнением, которое надо заменить, его основным преимуществом является расширяемость и кастомизируемость, а все его байндинг, енкодеры, пайлайны это переменные из можно менять как тебе хочется. Но да, как ты заметил это сложная технология и надо возиться, ляп-ляп и в прод не выйдет, хотя кто их знает, добавят фич чтобы он вел себя как нынешние альтернативы из коробки и все будут бездумно использовать их, как в свое время соапы. и думать что вот это вот и есть его предел

что за виндовс транспорт протоколы?

Named pipes, msmq.

его основным преимуществом является расширяемость и кастомизируемость

По сравнению с чем, особенно в контексте web api?

а все его байндинг, енкодеры, пайлайны это переменные из можно менять как тебе хочется

И что мне он может предоставить нынче из коробки? Soap сервер? Базовый tcp листенер с десериализацией, кострубатый rest поверх http1.1 без элементарных вещей вроде поддержки свагера?

Но да, как ты заметил это сложная технология и надо возиться,

Смысл, ради чего? Если можно взять все готовое затюниное под минимальный framework overhead и в случае web api с массой готовых решений на куда более высоком уровне программирования, лучшим перформансом благодаря более эффективной сериализации, транспортным/securtiy протоколам, с в 100 раз лучшей поджержкой на других платформах и дев комьюнити.

По сравнению с чем, особенно в контексте web api?

по сравнению со всем, по большому счету вся кастомизация вебапи сводится к тому что хмл или жсон, формат ответа вцф настраивается

И что мне он может предоставить нынче из коробки? Soap сервер? Базовый tcp листенер с десериализацией, кострубатый rest поверх http1.1 без элементарных вещей вроде поддержки свагера?

откуда я знаю, порт в разработке, что добавят то и будет, если они вообще закончат его пилить

Смысл, ради чего? Если можно взять все готовое затюниное под минимальный framework overhead и в случае web api с массой готовых решений на куда более высоком уровне программирования

все же почему-то берут дотнет кор, все берут еф, хотя есть даппер с минимальным оверхедом

лучшим перформансом благодаря более эффективной сериализации, транспортным/securtiy протоколам

вот его можно взять как есть и вбросить в байндинги, реализовав пару интерфейсов вызовами из донора

с в 100 раз лучшей поджержкой на других платформах и дев комьюнити.

офигенно сравнивать комьюнити мейнстрима с комьюнити тулы, которая в разработке....

все же почему-то берут дотнет кор, все берут еф, хотя есть даппер с минимальным оверхедом

Потому что можно поговорить о них и привести всё-таки аргументы, а в случае с wcf аргументы для его использования просто отсутствуют... Ответа на вопрос «чтобы что» просто не существует в современных реалиях.

у тебя неправильное мнение насчёт него, он как дотнер кор, каркас с мусорным наполнением, которое надо заменить, его основным преимуществом является расширяемость и кастомизируемость

Заглянул в асинхронность wcf , там до сих пор древний APM, ни о каких тасках речь не идет.. вангую что во всех тех extensibility points о которых речь даже асинхронного интерфейса может не быть.. наполняй не наполняй такое убожество оно неконкурентноспособно по сравнению с тем как сейчас делают веб сервера, даже от мс.

просмотрел сорцы, есть там асинхронность... насколько все хорошо/плохо не знаю. пусть выпустят пару апдейтов будет понятно, то что выпустили с .нет5 мало, в .нет6 вцф в ченджлогах не вижу

к новичкам очень скептично относятся

До всіх треба відноситись скептично
Ви ж помітили і інші недоліки в тексті?

dou.ua/...​rums/topic/35350/#2278270

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

комьюнити пишет порт и вполне может оказаться что через пару лет вцф вернётся в мир дотнета, заменив и вебапи, и жрпц как более полноценная технология

Вкусы специфичны у коммьюнити).

[sarcasm]
Миллениалы изобрели JSON-RPC
[/sarcasm]

Если без шуток, то уже год пытаюсь пхпшников в команде убедить попробовать protobuf, но пока безуспешно

А для чого пхпшнікам бінарний протокол?

Щоб почати переписувати мікросервіси на Go

Щоб потім сидіти і дебажити повідомлення в бінарному вигляді?

Жорстоко

Бінарний вигляд під капотом, звісно повідомлення можна подивитись в бінарному вигляді, але зазвичай дивляться вже готову структуру з заповненими полями.

ну protobuf старший за json-rpc, просто всередині гугла був :)

Дякую за статтю. Хотілося б порівняння з GraphQL, а також згадка OData. На останнє я натрапив недавно в гуглі, і чк зрлзумів це майкрософтська технологія, а таке привязане до одного стьоку стандартом не стане.

Сайт одата jQ використовує...для меню
xD

OData 4.01 Committee Spec Approved
01 Feb 2018

Його вже прикопали

Хоча деякі концепти впорядкування урлів — непогані

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

Что-то мне это неуловимо напоминает ... Может это?
en.wikipedia.org/...​_remote_method_invocation

Их там до**я, Corba, XMLRPC, DCom...
en.wikipedia.org/...​quest_Broker_Architecture
en.wikipedia.org/wiki/XML-RPC
en.wikipedia.org/...​ed_Component_Object_Model

В начале 2000-х называлась микросервисы назывались трехзвенкой.

В кінці 1990-х...

Хоча перший і останній проєкт з CORBA в нас був таки в 2000-му.

Все же не совсем понимаю разницу между REST и RPC. Наверное из-за отсутствия практики работы с RPC. И все же спрошу: при REST, по сути происходит ведь такой же удаленный вызов функции: вызов метода контроллера?

REST больше заточен на управление ресурсами и значительно легче. RPC же по сути процедурное API без каких либо идейных ограничений.

Видел что в основном используют для кодирования/декодирования сообщений в Kafka/etc.

Сравнивая гугловскую технологию с REST, здесь тоже находим свои плюсы:
HTTP/2.
Однако на данный момент gRPC не может полноценно функционировать в браузерах. Реализовать HTTP/2-общение в браузере невозможно

Тут я остаточно заплутався

вирогідно не розуміння предмету статті самим аффтаром виникло саме отут

Реализовать HTTP/2-общение в браузере невозможно
HTTP/2. REST зачастую использует более старую версию данного протокола — HTTP/1.1.

Ще раз наголошу, що REST — це архітектурний стиль, він не може використовувати якийсь протокол.
У цьому криється його гнучкість, ви можете хоч на TCP або UDP його реалізувати.
А RESTful веб-сервіси — так, вони використовують HTTP, але знову ж таки версія HTTP протоколу (1.1 або 2.0) ніяк не залежить від REST, а від того веб-сервера, на якому крутиться ваш додаток.

REST базируется на хттп, соотв. ни на каких tcp restful сервис реализован быть не может. Ну или это будет не restful сервис.
От версии ХТТП реализация сервиса не зависит, это да, если только в используемой версии хттп остались необходимые RESTу примитивы (а может в http/5 решат убрать http verbs, мало ли)

Це вам на .NET курсах розповіли, що REST залежить від HTTP? Тоді вам не варто було їх закінчувати, на жаль ((
REST — це архітектурний стиль, який накладає 5 обмежень на архітектуру вашого проекту:
1) Client-server
2) Cacheable
3) Stateless
4) Uniform interface
5) Layered system
І ніде тут немає жодного слова про HTTP. Клієнт та сервер можуть використовувати будь-який протокол. А ось RESTful web-API — це справді одна з реалізацій API, яка базується на HTTP.

К чему тут сухие выжимки из ваших лекций и шутки уровня студентов ваших курсов? Ограничения РЕСТа, а также диссертация Роя Филдинга всем давно известны. Но вам, как преподавателю курсов, нужно смотреть на проблему обширнее/глубже, а не «по учебникам».
Никто и не писал, что РЕСТ *зависит* от ХТТП, потому что дизайн (REST) не может «зависеть» (или иметь влияние) от имплементации (HTTP). Но учитывая, что Рой, на момент написания РЕСТа (как абстрактного, transport-agnostic арх. стиля), был членом рабочей группы по HTTP v.Next, то HTTP 1.1 сделали идеальным протоколом, который следует РЕСТу (клиент-сервер, стейтлес, кеширование, прям по вашим пунктам, как вы любите). Ну или РЕСТ сделали так, чтобы он идеально подходил под ХТТП 1.1 (они вышли почти в одно время).
При этом Рой да, не связывает РЕСТ и ХТТП явно, но никому и в голову не придет реализовывать РЕСТ over non-ХТТП, потому что тот «non-ХТТП» в итоге получится тот же ХТТП, но намного дороже, и юзать такую поделку сможете только вы в intranet-приложениях, т.к. глобальная инфра по-умолчанию благоволит только ХТТП (привет 80й порт).
Поэтому, когда говорят про RESTful API/service, то в 99.99% случаях говорят про REST over HTTP, потому что понимают сложность и безумие реализации оного на других транспортах, и только 0.01% людей с умным видом впаривают своим студентам «6 принципов REST», а если ты не реализовал REST over UDP, то «твои курсы не такие зашибенные», как «IT-Discovery».

Простая структура определения сервисов. Для этого используются .proto-файлы.
Простота определения контрактов. В REST для описания интерфейсов и документации нужно использовать сторонние инструменты и библиотеки — такие, как OpenAPI или Swagger. В gRPC происходит простое определение контрактов в .proto-файлах.

А в чому тут полягає простота?
У gRPC, як я зрозумів, потрібно вивчити цей формат .proto, навіть якщо я не хочу, а OpenAPI — просто набір з 10 анотацій, який ти вивчиш за 20 хвилин і зможеш використовувати в Java коді.

Анотації можна забути оновити, а на основі proto-файлів генерується серверна частина з маршрутизацією та моделями та повноцінний клієнт.

Або ж в OpenAPI спершу писати swagger.json та на його основі генерувати серверну та клієнтську частину, а писати swagger.json вручну боляче.

с таким подходом и proto-файл можно забыть обновить при изменении)) Чтобы не забыть что-то придумали тестирование (автоматическое).
Чтобы понять и (важно!) принять grpc, нужно сначала годик-другой попробовать сам protobuf хотя бы в среднеразмерном проекте(-ах). Так на пустом месте можно заиметь геморой размеров с галактику с версионированием, backward compatibility, отладкой, что и подходить к нему не захочется.

Спочатку оновлюється proto-файл а далі вже генерація коду.

Кожен бізнес захоче зачекати один-два роки.

ну, если «бизнес» говорит вам какие технологии использовать и когда, тогда мне вас жаль

Я писав про «бізнес захоче зачекати поки розберетесь з технологією» а ви пишете «бізнес каже які технології використовувати», це різне.

ну, мне показалось, что под «Кожен бізнес захоче зачекати один-два роки» имелось ввиду, что бизнес сам знает, какую технологию нужно юзать его разработчикам и плевать он хотел на их мысли и на то, есть ли у них экспертиза в ней.
Мой посыл был в том, что с протобафом можно работать, но НАМНОГО геморойнее, чем с text-based сериализаторами. А в более-менее больших, публичных и активно развивающихся системах, при отсутствии жесткой самодисциплины к написанию backward compatible кода (это бывает сложно) выроятность выстрелить себе в ногу растет с каждым новым релизом.

В мене робота з protobuf переважно успішна, окрім одного разу.

Але у відомому сервісі по продажу білетів, хай SomeAviaTicketSales, зробили подвійну серіалізацію бо треба було передавати через чергу повідомлень. Звісно подвійна серіалізація там була зайва.

С переходом на микросервисы в проекте появляется такая особенность, как распределение ответственности.

Цікаво, а чому?
Якщо я маю моноліт, розбитий на слабо-пов’язані модулі (компоненти), то в кожного модуля є своя зона відповідальності. Більше того, в теорії та у кожного розробника є зона відповідальності — це його модулі.

более трех лет участия в коммерческих проектах.

Схоже, що в людини постджунський період Данінга-Крюгера

По всьому тексту є помилки
— мікросервіси автоматом починають працювати з окремими платформаим
— моноліт можна тільки на одному сервері тримати
— запуск окремих віртуалок гірший за vendorlock
— відсутність e2e тестування при мікросервісній архітектурі
— «неможливість» тестування модулів в «моноліті»
— json у нас не жметься в 2k21

При этом в микросервисах мы можем на одной машине разместить множество легковесных сервисов,
В монолите все части приложения находятся в одном месте

У чому тоді різниця між монолітом та вашими мікросервісами?

Микросервисы можно при желании заскейлить сожрав только необходимое количество Ram/Disk space. С монолитом придется попариться, особенно если в нем есть всякие бекграунд задачи, возможно придется навешивать что-то типо feature toggling. Так же проще с разделением сети, разные микросервисы могут иметь доступ только к определенным подсетям, с монолитом чуть сложнее.

Обновление. Монолиты сложно обслуживать и добавлять в них новый функционал.

Не розумію, чому автор весь час прослизає, що моноліт — це завжди погано.
Якщо моноліт грамотно написаний і структурований, то в ньому все просто і розібратися, і додати новий функціонал, і вивчити.

Почему бы не сделать все это одним приложением с несколькими или даже общей базой данных? Именно в этом суть микросервисного подхода в построении архитектуры приложений.

Вибачте, але в мікросервісній архітектурі прийнято ізолювати мікросервіси (і їх сховища даних), а коли всі мікросервіси використовують загальну базу даних, це анти-патерн.

The drawbacks of this pattern are:

Development time coupling — a developer working on, for example, the OrderService will need to coordinate schema changes with the developers of other services that access the same tables. This coupling and additional coordination will slow down development.

Runtime coupling — because all services access the same database they can potentially interfere with one another. For example, if long running CustomerService transaction holds a lock on the ORDER table then the OrderService will be blocked.

Single database might not satisfy the data storage and access requirements of all services.

It depends (at least on scale of the project).

Несмотря на столь юный возраст, gRPC уже подвинул во многих крупных сервисах популярнейший REST API. Но сможет ли он вовсе заменить его? Чтобы ответить на этот вопрос, давайте сравним фреймворки.

Знову ж таки — REST це не фреймворк

а отправка данных проходит по постоянному каналу без необходимости сериализации
Работа с Protobuf. В REST для передачи данных применяется текстовый формат JSON, который не сжимается. Protobuf — это бинарный формат. Используя его, мы избегаем передачи лишних данных

Я щось упускаю або якщо мій Java об’єкт перетворюється на масив байт у форматі Protobuf для відправки — це і є серіалізація?

протобуф «зжимає» всякі там інти в varint, строки він не «зжимає», міф проф уникнення зайвих даних.

Дякую за статтю, але є кілька важливих зауважень

Фреймворк gRPC: как он упрощает задачи разработчика и почему лучше, чем REST API

REST API — це архітектурний стиль. Як можна порівнювати фреймворк та стиль? І стверджувати, що щось із них краще?

без необходимости сериализации

та ладн)
дьоргати через свагер-контролер прослойку grpc, це мазахізм. +не ясно що цим хотіли показати.
як і частиною про

AWS Lambda и Azure Function

.
bloomrpc як варіант щоб потикати \ показати стрімінг складову grpc
респект, що взагалі втягуєте тех статті в доу, але, імхо, в такій подачі вони тільки більше конфюзять =\

Хорошая вводная статья. Но было бы еще интересно услышать про опыт с gRPC Streaming)

В этой статье я расскажу о достаточно новом фреймворке gRPC для API.

Це ваша авторська стаття чи все ж переклад?

Питання й досі актуальне бо частини тексту вже зустрічав раніше в англомовних статтях, але відсутні посилання на ці статті.

Приклади коду також є, але відсутнє посилання на репозиторій, щоб глянути повну картину.

Знаменитая дилемма Эскобара

Не совсем. Однозначного ответа «используй это» дать нельзя. Есть ряд факторов влияющих на то, от чего мы получим больше выгоды: особености конкретного проекта, сколько есть времени на реализацию подобного механизма общения, наличие специалистов знающих как работать с gRPC и т.п.. В идеальном кейсе, я бы всегда использовал gRPC для внутреннего общения между сервисами (если есть необходимость получить результат процедуры сейчас, если же нет — скорее выбрал бы очередь), а REST API для взаимодействий с браузерами.

ты наверное и физбаз через месседжинг писать будешь :)

Как в Экселе, нажал княпачку Сохранить. Оно и сохранилось.

А кстати, почему это до сих пор в современной версии нет микросервисов и мессенджинга???
Срочно доработать!

Шо тут, WCF переизобрели?
Если серьезно, то можно уже на 100% это эффективно использовать из браузера? Так чтобы в середине проекта не оказалось «ой а тут так нельзя».

Request—response protocols date to early distributed computing in the late 1960s, theoretical proposals of remote procedure calls as the model of network operations date to the 1970s, and practical implementations date to the early 1980s. Bruce Jay Nelson is generally credited with coining the term “remote procedure call” in 1981.[1]

Через прокси rest->grpc transcoder (envoy, istio, ...) - вполне себе можно, фронтенд даже не будет знать, что с grpc общается.

Через прокси rest->grpc transcoder (envoy, istio, ...)

Ага, посмотрю. Но хотелось, чтобы все было без намека на конченый рест. Хочу просто дергать методы из джаваскрипта типа GetEmpoyeesWithFinalizedSalaries без конченых нравоучений по построению урлов, использованию методов и кодов.

Ну, это уже grpcweb, когда клиента в JS генерим из protobuf-протокола сервиса.

В браузерах я бы пока не использовал :) Вот тут немного инфы на этот счет: grpc.io/...​pc-web/#the-grpc-web-spec

Подписаться на комментарии