Как стать автором
Обновить

Комментарии 63

Добавлю от себя небольшой рецепт счастья: Blazor wasm + gRPC(code first) - это очень удобно. Ну или по крайней мере мой опыт был довольно успешным :)

Blazor wasm сразу вызывает 2 опасения - 1) как на это искать людей 2) как это диагностировать, если что-то отвалилось вне девелоперской сети. Всё в бинарке и wasm, и код - и запросы.

А так, конечно, всегда соблазнительно вместо js перетянуть какой-то "более правильный" язык на фронт.

1) своих переучить, технология довольно простая в освоении

2) там довольно понятные стектрейсы в случае ошибок. Ловушки с читабельными исключениями тоже доступны.

асинхронный eventual consistency-вариант вместо синхронного вызова — это костыль. 

HTTP Gateway — это отдельно стоящий сервис, который работает как прокси для gRPC-сервиса.

Ладно

Ну я так понял про HTTP Gateway это было в контексте протаскивания протобафа на эндпоинты, т.к. протобаф в браузер не протащишь (пока). И это тоже костыль, и автор вроде нигде не писал что этот гейтвей - хорошее решение. Скорее это надо читать так: хорошего решения сейчас нет, но, как костыль, есть вот этот гейтвей если очень хочется

То есть, только для высоких нагрузок? Проблема с совместимостью протокола, поддержки и тестирования пересилитвают скорость реста? Правильно я понял?

Если в системе только c#, имеет ли смысл использовать сразу Orleans + протобуф?

Есть ли вообще какая-то мало малькая инфраструктура вокруг сабжа? TTL, кластеризация, например?

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

Вопрос про Orleans - тут за скоуп выходит, можно использовать, можно не использовать, это ж фреймворк, определяющий как будет выглядеть довольно толстый слой кода, а gRPC - только транспорт) В этом смысле ответ на вопрос про Orleans зависит от домена - что вообще за система, а gRPC где угодно можно использовать.

Про инфраструктуру - лучше каждую конкретную фичу гуглить. Например, TTL в некотором виде есть (т.н. deadlines), но его поведение с grpcStreams нас скорей удивило.

Стоит упомянуть gRPCurl, очень удобная штука для всяких автотестов

И grpcui. Недостаток утилит конечно в том, что при отсутствии рефлексии в grpc сервисе, надо ручками с помощью protoc компилировать protoset файлы из proto файлов контрактов. Обычно ок, тоже можно автоматизировать.

Мы просто proto файлы скармливали безо всякой компиляции, всё работало

в тест среде можно деплоить с HttpApi - получая rest+сваггер обёртку над этим grpc, которую можно дёргать по-старинке курлом или из браузера.

Спасибо. Мы тогда пользовались BloomRPC, в видео есть, а из статьи вырезал чтоб не раздувать пост.

Если честно, то не понял сравнения с Kafka. Как можно сравнивать синхронный (gRPC, REST, JsonRPC и прочие) и асинхронный (очереди [*MQ] и журналы [Kafka]) принципы взаимодействия? Совершенно разные подходы не просто в коде, а вообще во всей системе и логике.

Всё так. Но

  • Неоднократно встречались попытки натянуть sync over async.

  • Grpc streams не request-response штука и в определённых сценариях может быть альтернативой

Синхронность и асинхронность мало общего имеют с очередями и интернет-протоколами. Они связаны с особенностями потока управления.

Кафка вполне может использоваться для синхронного взаимодействия. Grpc - для асинхронного.

Их корректно сравнивать как средство доставки сообщений, например.

А можете как-то кратко описать кафку для синхронного и чтоб это не было мрачно-костыльно?

Как техническое средство, естественно, кафка для синхронного взаимодействия подходит не так хорошо, как непосредственный сетевой вызов. Поэтому, "некостыльно" - наверное, не могу.

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

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

Что насчет WCF? Одно время хотели отказаться от него в пользу gRPC, учитывая, что protobuf в проекте уже есть — однако в итоге до этого дело не дошло. Интересно, какие у вас соображения на этот счет?

Работаю в букмекерской конторе - у нас было, что сайт вешает ядро на WCF запросами в какие-то моменты - вырастает количество потоков и всё умирает. Перевели все API на grpc и всё стало хорошо

WCF не портирован в .NET Core, насколько я знаю

Не портирован, но и упоминаний про него небыло нигде.

Вообще есть сторонний порт на каких-то зачаточных стадиях, но чисто для переноса. Лучше с WCF переписать

Это проблема, да. Есть конечно Core WCF, но его в продакшн не затянешь

Core WCF уже можно в продакшн, если вам хватает имеющихся фичей. Пока только начинают делать генерацию WSDL, но в целом решение живое. В своих проектах и в обсуждениях на гитхабе критичных проблем не видел.

Мы отказались от остатков WCF году в 2014-2015 ещё. Наш опыт под высокой нагрузкой - крайне негативный. С учетом того что мы 80% уже перевели на .NET Core и хотим дожать в 2022Q1, рад что сейчас не надо портировать ещё и это!)

Преимущества и недостатки gRPC изначально связаны с парадигмой взаимодействия.

Если предполагается restful взаимодействие с понятной предметной областью - то классический Rest однозначно лучше. В его соглашениях все взаимодействия описаны, и есть много средств, успешно их использующих.

А если требуется RPC в произвольной форме - тогда, конечно, grpc на данный момент в общем случае самый логичный первый выбор.

P.S. Очень жаль, что не рассказали о том, что протобаф доступен без всякого grpc и протофайлов как форматтер в "обычном" рест-взаимодействии. Может сложиться впечатление, что для решения всех описанных проблем обязательно тянуть весь grpc.

Если предполагается restful взаимодействие с понятной предметной областью - то классический Rest однозначно лучше.

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

Ну т.е. можно сказать ведь, что "если предполагается взаимодействие через TCP-сокеты, то классическая работа с сокетами однозначно лучше". Трудно спорить. ;)

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

Без gRPC — да.

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

Гм. Мне это почудилось, что между "можно без протофайлов" и "можно без протофайлов, но с внешней примочкой" есть неуловимая смысловая разница? Или мне не почудилось, и она действительно есть?

А не майкрософтовские неймспейсы у нас не в почете?

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

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

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

А не майкрософтовские неймспейсы у нас не в почете?

Не понял вопроса.

protobuf - это всего лишь формат сериализации. такой же как json, msgpack, xml итд. конечно, его можно использовать отдельно от grpc (хотя msgpack и будет в этом случае лучше), как и любой другой input/output-formatter в aspnet mvc. и да, его можно использовать для сериализации и за пределами http rest/mvc. довольно странно, что об этом надо отдельно упоминать и как-то акцентировать в статье про grpc.
тот же json поддерживает json schema. но про него далеко не все знают, а используют для валидации ещё в меньшем количестве случаев. для xml тоже есть xml schema. proto-файлы это такой же контракт. и да, если извернуться, то можно собирать валидный protobuf без proto-файлов, но зачем?

Чтобы использовать RESTful стиль взаимодействия с преимуществами малого объёма передаваемых данных.

Упоминать надо, поскольку на моей практике часто люди, вместо того, чтобы точечно решить проблемы с этим объёмом, начинают переделывать вообще всё на grpc.

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

Это не самоцель, это выбор, на основании которого надо принимать дальнейшие решения.

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

НЛО прилетело и опубликовало эту надпись здесь

Postman Now Supports gRPC

https://blog.postman.com/postman-now-supports-grpc/

Мне кажется одна из больших "болей" в микросервисах - это версионирование, жаль, что в статье это не затронули. По rest уже есть некие стандартные приёмы, библиотеки, типа делаешь /v2/ и дальше двухшаговая миграция. А как это работает с gRPC и protobuf? Есть какой-то стандарт, что делать с контрактом при необходимости сделать несовместимые изменения? Просто генерим второй контракт и дублируем все затронутые классы? Есть ли набор ошибок передающих статус deprecated?

Ничего хитрого, если нужны breaking chages. Тем не менее, для определенных сценариев типа ренеймов и удаления полей есть специально предусмотренные штуки в protobuf. А так - да, v2.

Статуса deprecated нет, и, боюсь, без ручной обработки такой ситуации - это будет просто кейс "делаем RPC с некорректным контрактом"

deprecated есть (пролистать ниже - в конце блока options), но не всеми поддерживается

Мне кажется вопрос был про ошибки, статусы и вот такое, но тут остаётся только догадываться, конечно.

Никогда не понимал зачем(ну кроме очень узких задач) нужен grpc для микросервисов(сразу вспоминаю про корень всех зол). Но на примере .NETa использование grpc выглядит абсурдным, ведь майки для таких узких задач специально создавали wcf. Наверное wcf от гугла звучит круче чем от майков.

Wcf очень многословен, использует как базу по умолчанию тяжёлый и медленный xml. И вас не смущает, что его развитие по сути было остановлено 12 лет назад? По сути можно ещё предложить сейчас писать веб приложения на вебформс. Ушло уже время, ушло, это медленные, неудобные, неподдерживаемые технологии, которые не построены на современных принципах.

Выше ответил - нагрузку не держит. При этом не работает с сервисами на python, golang, С++ и так далее. И это не учитывая очевидный факт что технология умерла.

При этом не работает с сервисами на python, golang, С++ и так далее.

При наличии WSDL не работает, или вы имеете вы виду что-то другое?

Нет, я забыл за давностью лет, что там не всё было самописное микросфортовское, сорри - вы правы, должно работать) Но остальные пункты не отменяет.

Статья печалька, много умных слов мало умных мыслей.

Grpc как и rest работает поверх HTTP, как это ни странно)) Использует HTTP/2 да это хорошо, но он требует SSL, что наводит на мысль что при маленьких запросах затраты на согласование коннектов будут не соизмеримы с временем выполния самого запроса, это надо учитывать.

То что rest не умеет Contract first, бред полный.

Подход зависит от инструментов, хотите Contract first будет он, с генерацией не только контроллеров но клиенсткой стороны скажем на TS или каком другом языке.

openapi описывает контракты и они не обязательны, вы сами то себя слышите?

То-есть схема вам говорит я жду обект типа А с полями 1 и 2 такого-то типа, вы уверенно пихаете в метод болт и он у вас проходит так что-ли получаеться? Ну если у вас так продукт построен то мне жаль деньги потраченные на его развитие.

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

но он требует SSL

Это не обязательно, хотя и приветствуется:

If an HTTP/2 endpoint is configured without TLS, the endpoint's ListenOptions.Protocols must be set to HttpProtocols.Http2. An endpoint with multiple protocols (for example, HttpProtocols.Http1AndHttp2) can't be used without TLS because there's no negotiation. All connections to the unsecured endpoint default to HTTP/1.1, and gRPC calls fail.

Если настроить сервер на Http2 only то можно и без TLS

.ConfigureWebHostDefaults(webBuilder =>
{
    webBuilder.UseStartup<Startup>();
    webBuilder.ConfigureKestrel(options =>
    {
        options.ConfigureEndpointDefaults(listenOptions =>
        {
            listenOptions.Protocols = HttpProtocols.Http2;
        });
    });
})

Подход зависит от инструментов

Есть стандартные средства, встроенные в платформу/фреймворк, есть какие-то инструменты сбоку. Это не одно и то же. Выше в комментариях аналогичная дискуссия, не вижу смысла углубляться.

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

И без openAPI и без всякой схемы сервис может кидать 400, если получил не то, что ожидалось. Это не про compile time проверку, очевидно.

мне жаль деньги потраченные на его развитие.

Baring Vostok инвестировал $13 млн в российскую платформу автоматизации маркетинга Mindbox — Маркетинг на vc.ru

Не надо нас жалеть, у нас всё хорошо, спасибо.

Много бойлерплейт-кода: создать HTTP-клиент, HTTP client factory, договориться о сериализации (JSON, XML или другие варианты), учесть различные форматы дат, чисел и так далее, кейсинг. Соответственно, много возможностей для возникновения ошибок — нужно писать DTO-классы специально для транспорта.

gRPC тоже не является серебрянной пулей которая это целиком решает. Например использование nullable типов в C# может выстрелить когда какой-нибудь клиент захочет его использовать из языков где нет nullable типов. Незнаю как сейчас но раньше decimal не поддерживался что требовало создание своего типа который после передачи надо было склеивать в родной тип decimal на стороне внешнего клиента и в обратную сторону аналогично.

Добавлю инструмент для работы с gRPC, это Kreya, в целом довольно удобно тестировать запросы.

У REST не очень хороший перформанс в сравнении с gRPC.

Хотелось бы увидеть каких-то доказательств этого утверждения. Что вообще подразумевается под «перформансом»? Накладные расходы на сериализацию-десериализацию? Ну так шли protobuf а не json/xml, если тебе это важно.

Ну и, традиционно, автор понятия не имеет, что такое REST.

Скорее всего, называет для краткости HTTP без дополнительных прикладных протоколов сверху просто REST-ом.

gRPC тогда — тоже REST. Он поверх чистого HTTP-работает и никаких REST-парадигм не нарушает (насколько мне известно).

Перформанс - комплексно, сериализация, пересылка более жирного пейлоада, GC от этого всего. В тексте на строчку ниже пишу, что при замене популярных человекочитаемых форматов на что-то другое будет лучше.

Можешь раскрыть, в чем будет преимущество - взять protobuf отдельно?

Тезис 1: gRPC — это имплементация REST-архитектуры поверх протокола HTTP/2 с использованием формата Protobuf для передачи данных. gRPC-система удовлетворяет всем критериям Филдинга, и даже в некотором смысле явлеяется более «REST» чем стандарные JSON-over-HTTP API, которые принято обозначать словом «RESTful», поскольку является, как изящно выразился Филдинг, gRPC является «hypertext-driven» системой, если рассматривать .proto-файл как формат гипертекста.

Тезис 2. Если под «REST» понимать сложившуюся парадигму разработки т.н. RESTful API, которая, грубо говоря, сводится к широкому и семантичному использованию фич протокола HTTP (HTTP-глаголов, статус-кодов ответа, передачи метаданных в заголовках, URI как идентификатор ресурса и т.п.) то совершенно непонятно, какие могут возникнуть накладные расходы, если в качестве формата запроса и ответа использовать Protobuf. Более того, REST на этом фоне выигрывает, поскольку явные метаданные (метод запроса, URI, заголовки) можно читать, не вычитывая тело ответа, и тем самым гораздо эффективнее реализовать multi-layered системы.

Тезис 3. Если под «REST» понимать строго RESTful API с использованием текстовых форматов данных (JSON/XML), то, разумеется, да — 1) JSON более многословен и 2) его сложнее парсить.

По поводу первого — голый JSON никто по сети не гоняет, вообще-то в мире есть gzip. JSON+GZIP на реальных примерах отличается от протобуфа в пределах статистической погрешности в объёмах (вот исследование Auth0, например: https://auth0.com/blog/beating-json-performance-with-protobuf/)

По поводу второго в интернете полно мифологии, но нет никаких реальных цифр. Да, это правда — многие мейнстримовые JSON-парсеры очень медленные. Но вообще-то они медленные потому, что всем наплевать на накладные расходы JSON-парсера. А если не наплевать — то вон разработчики simdjson заявляют, что добились производительности в гигабайты в секунду: https://github.com/simdjson/simdjson — и что-то я сомневаюсь, что protobuf быстрее.

Наконец, не надо забывать, что мало распарсить протобуф — надо его ещё конвертировать в структуры данных языка. И тут как бы внезапно во многих платформах это придётся делать… через JSON. Ну там браузеры, например, никаких ваших бинарных форматов не поддерживают, так что протобуф надо сначала распарсить, а потом из него JS-объекты сгенерировать, что работает в лучшем случае со скоростью JSON.parse, а в худшем — накладные расходы на две конвертации просто складываются.

Это очень интересно, жаль вопрос был про другое. Нет смысла в такой дискуссии - когда на вопрос по существу, причём вопрос был конкретный и по конкретному предложению собседеника - получаешь лекцию на отвлечённую тему.

Я, видимо, что-то пропустил.

Хорошо, вернёмся на шаг назад. Вас же не затруднит предоставить какие-то ссылки в подтверждение тезиса «у REST не очень хороший перформанс в сравнении с gRPC», да?

Ссылка на публикацию по этой теме на хабре гуглится элементарно - Сравниваем производительность REST и gRPC / Хабр (habr.com) Давай опустим ту часть, где ты ещё раз энциклопедическими выкладками доказываешь, что это совсем не то? Сравнивать перформанс REST (парадигмы/архитектуры - как ни назови, явно чего-то далекого от конкретной реализации) и gRPC - занятие, очевидно, абсурдное. Я лучше объясню, как так получается, и на этом, надеюсь, вопрос будет закрыт.

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

Во-вторых, эта публикация - умеренно отредактированная адатация выступления с конференции; не все формулировки, особенно в формате живого выстуления, возможно сделать идеально точными - как в силу недостаточного мастерства спикера, так и в угоду здравому смыслу, краткости и простоте восприятия. Совсем по-простому - превращать доклад в юридический бубнёж вида "включая, но не ограничиваясь, JSON и иные human-readable форматы, ..." я не хочу, даже если б мог - слушать такое невозможно. Можно ли было в текстовой версии улучшить формулировки? Да, можно)

В указанной публикации не написано, какой парсер / сериализатор JSON используется, а без этого сравнение некорректно (т.к. сравнивает не производительность «REST» против gRPC, а производительность изкоробочных .NET-реализаций).

P.S. Ваши попытки прикрыть банальное незнание терминологии болтовнёй про контекст выглядят глупо. Дайте строгое определение, что вы с чем сравниваете.

Нет, дружище. Ты начал с комментирования автора, к этому же вернулся (несмотря на прямой вопрос по существу) - развлекайся дальше сам.

Как угодно. Просто закончим на том, что раздел «Чем gRPC лучше REST» вашей статьи несостоятелен, поскольку вы отказываетесь даже дать определение того, что вы имеете в виду под «REST», не говоря уже о доказательствах заявленного тезиса.

Про параметр gRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA неверно написано про GOAWAY. В документации https://chromium.googlesource.com/external/github.com/grpc/grpc/+/refs/tags/v1.28.1/doc/keepalive.md сказано
"

  • Why am I receiving a GOAWAY with error code ENHANCE_YOUR_CALM?

    • A server sends a GOAWAY with ENHANCE_YOUR_CALM if the client sends too many misbehaving pings. For example -

      • if a server has GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS set to false and the client sends pings without there being any call in flight.

      • if the client‘s GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS setting is lower than the server’s GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS.

"
Т.е. параметр gRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA на эту логику не влияет.

Фразу "for example" вы переводите как "полное перечисление всех сценариев"? Зря.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий