Comments 31
gRPC это далеко не зарождающийся формат для микросервисов. Он уже очень давно используется в продакшене в вцсоконагруженных системах.
Очень хочется посмотреть на пример микросервиса, где 10 минут ушло на разработку REST версии по сравнению с 45-минутной gRPC. И потом сравнить производительность (и затраты бабла на хостинг) при высокой нагрузке.
> elective message compression. In gRPC a streaming RPC can decide to compress or not compress messages. For example, if you are streaming mixed text and images over a single stream (or really any mixed compressible content), you can turn off compression for the images. This saves you from compressing already compressed data which won't get any smaller, but will burn up your CPU.
First class load balancing. While not an improvement in point to point connections, gRPC can intelligently pick which backend to send traffic to. (this is a library feature, not a wire protocol feature). This means you can send your requests to the least loaded backend server without resorting to using a proxy. This is a latency win.
Heavily optimized. gRPC (the library) is under continuous benchmarks to ensure that there are no speed regressions. Those benchmarks are improving constantly. Again, this doesn't have anything to do with gRPC the protocol, but your program will be faster for having used gRPC.
As nfirvine said, you will see most of your performance improvement just from using Protobuf. While you could use proto with REST, it is very nicely integrated with gRPC. Technically, you could use JSON with gRPC, but most people don't want to pay the performance cost after getting used to protos.
> We found that regardless of the serialization/deserialization method used for protobuf, it was consistently about 3x faster for serializing than JSON. For deserialization, JSON is actually a bit faster for small messages (<1kb), around 1.5x, but for larger messages (>15kb) protobuf is 2x faster. For gzipped JSON, protobuf is well over 5x faster in serialization, regardless of size. For deserialization, both are about the same at small messages, but protobuf is about 3x faster for larger messages.
И это только про сериализацию.
Это означает, что когда микросервис получает несколько запросов от более чем одного клиента, он должен обслуживать их по одному, что замедляет работу всей системы.
О как. А пацаны то и не в курсе. ;) </sarcasm>
Явно что-то другое имелось в виду. Такое ощущение, что статья написана без осмысления, что стоит за утверждениями с практической точки зрения.
Например, про ту же генерацию кода в gRPC. В чём преимущество перед REST я так и не понял, с учётом того, что Swagger - опционален. За несколько десятков проектов на .net/.net core с rest сервисами, ни разу не использовал его.
Поскольку он является сильно сжатым форматом <...> Передача данных происходит быстрее, потому что Protobuf уменьшает размер сообщений и служит легким форматом обмена сообщениями.
Откуда инфа, что protobuf что-то сжимает? Да, там используется "varint encoding", но в случае строк, насколько я знаю, никакого сжатия нет. По моему опыту, как раз таки строки составляют большую часть обмена между сервисами.
GRPC примерно в 7 раз быстрее REST при получении данных и примерно в 10 раз быстрее, чем REST при отправке данных для этой конкретной полезной нагрузки. В основном это связано с плотной упаковкой буферов протокола и использованием HTTP / 2 в gRPC
Можно ссылку на этот бенчмарк? По описанию складывается впечатление, что это сравнение не gRPC vs REST, а HTTP/2 vs HTTP/1.0 причем на специфических кейсах, где у HTTP/2 есть преимущество. Что мешает передавать JSON в стримах по HTTP/2?
Ускоряет передачу данных, удаляя множество обязанностей, которыми управляет JSON, поэтому он может сосредоточиться исключительно на сериализации и десериализации данных.
Сложно что-либо понять из этого предложения. Это точно не перевод?
По поводу скорости компрессии — вот, думаю этого достаточно? auth0.com/blog/beating-json-performance-with-protobuf
Есть куски, взятые из документации, которые было сложно перефразировать.
А что все-таки имелось ввиду? Что за "множество обязанностей, которыми управляет JSON"? Можете своимим словами объяснить?
По поводу скорости компрессии — вот, думаю этого достаточно?
Так я писал не про скорость компрессии, а про отсутвие самой этой компрессии в protobuf. Да, будучи бинарным форматом, он конечно более компактен, чем текстовый JSON. Но реальный выигрыш будет сильно зависить от содержимого сообщений.
docs.microsoft.com/en-us/aspnet/core/grpc/comparison?view=aspnetcore-5.0
devblogs.microsoft.com/aspnet/grpc-vs-http-apis
По словам Руана Фернандо, внедрение простой службы gRPC занимает около 45 минут. Реализация веб-API или REST API занимает всего около 10 минут
это мне кажется некорректное сравнение — примерно как сравнивать языки программированию по эффективности написать Hello World. Тут не учитывается стоимость и потраченное время на поддержку и изменение. В REST с точки зрения использования есть проблемы с обработкой ошибок, таймаутов, отмены запросов, нет валидации контрактов из коробки. И сверху всего этого — нередко REST api является по факту грязной реализацией RPC
я вижу только один плюс REST — текущая поддержка инструментов и легкость создания. Но вот лучше ли это в поддержке и эволюции — вот тут сомневаюсь.
Да, но тут скорее что бы заставить из коробки работать gRPC нужно потратить больше времени и сил
ну может обычно выходит что замеряется сколько времени потратит человек у которого уже есть опыт в REST но нет опыта в rRPC?
насколько я знаю, уже есть curl для gRPC, postman, и расширения для браузера для облегчения отладки с gRPC. А у Гугла кажется и лоад балансеры уже могут в gRPC. Основная проблема с gRPC мне кажется именно в повседневной рутине — написал rpc вызов, потом надо затестить, отладиться. И вот это вероятно удобнее в REST.
Но.
1) те же строгие контракты из коробки — великое дело. То что энфорсится на проектах бест-практиками, соглашениями, гайдлайнами — очень часто не работает. Попробуйте например обеспечить единый codestyle форматирования на 10 разных команд. И попробуйте нарушить форматирования если gofmt сразу даст по рукам. Большая разница. Тоже самое про контракты апи и их проверку.
2) Тоже самое по части обработки ошибок — частая ситуация когда микросервис получает 500 Error «что-то пошло не так», и не может дальше решить что с этим делать — http статусы малополезны для обработки ошибок, потому что для 500ки может быть просто ворох различных ошибок бизнес-логики, и это можно отразить только в теле запроса каким-то выработанным стандартом обработки ошибок. Опять таки, да, можно сделать библиотеки и тд. но нужно ещё заэнфорсить это по всей компании. Если же обработка ошибок органично ложится на структуру обмена сразу — это намного лучше.
3) обработка таймаутов. Ошибки в конфигурации таймаутов — частое явление. Итого выходит что вы даёте POST запрос, который добавляет сущность, и получаете скажем 503, но на деле он выполнился, просто один сервис в цепочке имел допустимый таймаут обработки запроса ниже чем следующий
4) как отменить запрос в REST? Сделать компенсирующий? Например истёк дедлайн на обработку запроса, и значит нужно обезопаситься от ситуации когда этот запрос всё-таки будет успешно обработан, а мы собираемся вернуть клиенту ошибку. В gRPC отмена запросов есть сразу как встроенный механизм
Оверхед на создание конектов? Медленная скорость передачи сообщений в REST?
Берём HTTP-клиент с полной поддержкой HTTP2, вместо JSON используем Protobuf и вот у нас уже REST API не в 7-10 раз медленнее передаёт сообщения, а всего 1.x раз (x — оверхед на передачу обязательных HTTP-заголовков, которых, наверное, больше чем в gRPC, но я не проверял).
Компрессия передаваемых данных?
Это есть в самом HTTP.
Балансировка без использования прокси-балансера (т.е. клиент сразу отправляет запрос на нужную ноду)?
Вспоминаем про забытый в статье HATEOAS, который является обязательным для REST. И вот у нас сервер сообщает клиенту на какие URL-ы он должен обращаться, тем самым осуществляя балансировку нагрузки без прокси-балансера.
Итого можно убрать эти пункты из списка отличий, на который надо смотреть при выборе REST API vs gRPC.
HATEOAS, который является обязательным для REST
А без него REST уже не работает?
По словам Роя Филдинга, API квалифицируется как «RESTful», если соответствует следующим ограничениям:
Ссылку на слова Филдинга приведёте?
Было бы неплохо сравнить .NET 5 а не NET Core 3.0.
Основное преимущество, за счёт чего gRPC выигрывает у REST - это потоковая передача данных, т.е. когда соединение устанавливается один раз. У REST это соединение устанавливается заново каждый раз, и выигрыш идет в основном мз-за этого, так как при установке соединения делаются все необходимые процедуры типа SYN/ACK, SSL и др. заново, с нуля.
Двунаправленные стримы grpc это круто. Они кстати уже имплементированы для вашего языка программирования?
А вообще grpc это http2 запрос с определенным content-type, у которого в боди лежат бинарные данные.
т.е grpc запросы можно и через постман при желании слать - нет никакой магии
Вот несколько подробностей о Protobuf:
Независимость от платформы и языка, например JSON
Эээ, что? Какая зависимость у JSON от платформы и языка? Да такая же и у протобуфа. Или тут имелось ввиду, что у Protobuf такая же независимость как и JSON, тогда простите я не понял Ваш русский.
Букаф много, но ни о чём.
Во-первых, gRPC это фреймворк. Это значит, что в нём есть готовый сервер, синхронный и асинхронный, многопоточный и нет, такой же клиент, а также кодогенератор данных и сервисов.
Во-вторых, в grpc не обязательно использовать protobuf и транспорт http/2. Вместо протобафа можно взять, например, flatbuffers, а вместо http/2 реализовать каналы хоть через голубиную почту.
В-третьих, скорость между парсингом Json, даже на потоковом rapidjson и том же flatbuffers (протобаф не использую по религиозным соображениям), не в семь раз, а в десятки и даже сотни при передаче массивов структур. Особенно, при обмене внутри ЦОД между микросервисами.
В-четвёртых, контракты в виде IDL, очень упрощают жизнь.
В-пятых, при небольшой предварительной подготовке фреймворка под себя, добавление новой команды (без реализации логики) в gRPC занимает около минуты.
Да он не идеален. Да требует больших компетенций, чем Rest. Поэтому, для взаимодействия между микросервисами я использую gRPC, а для взаимодействия с клиентскими приложениями - RestAPI.
Кстати, при выборе между gRPC и Thrift был выбран gRPC.
Я использую grpc и вижу много непонимания. Многие новички думаю что grpc это больше про перформанс. Много статей/видео где рассказывают о замене REST/web-socket на grpc и выигрыше в скорости (обычно всё без конкретных бенчамарков а сылки на "авторитетный ресурсы").
Проблема в том что у новичков простое мышление - JSON текстовой и нет схемы, значит он больше и медленее protobuf. GRPC использует protobuf, значит он быстрее.
Проблема в том что немногие хорошо разбираются в сетях и упускают протоколы. А сеть обычно занимает намного больше времени чем конвертация данных.
GRPC работает поверх HTTP2, там есть такие вещи как Flow Control например. Они могут поточь с "честностью обслуживания", но за них надо платить и могут быть вам не нужны.
Java GRPC использует использует модную в наши дни реактившину. То есть сообщения при стриминге запрашиваются, по умолчанию, по одному. Насколько это влияет на производительность, легко проверить. Вместо посылке обычного потока (repeated ObjectA), пошлите батчи по 100+ штук (repeated message ObjectList {repeated ObjectA}). В моем случае было ускорение на 30%+ процентов.
Самое обидное что изменять настройки Flow Control и реактившины в java grpc сложно https://github.com/grpc/grpc-java/issues/6696#issuecomment-893935694 (хотя java кажется единственная полностью асинхронная и создавалась для этого). Здесь разработчиками рассказывается что java асинхронная и что flow control можно легко отключить, но про flow control это уже не так https://youtu.be/EEEGBwEA8yA?t=938.
Еще есть странности, grpc HttpOk клиент быстрее дефолтного Netty Client (который использует 90%+ людей). Это пытаются пофиксать, но пока не получается (несколько PR-ов откатывалось https://github.com/grpc/grpc-java/issues/6696).
Про текущие сложности с load-balancing в k8s здесь обсуждать не будем. Их можно обходить, но о самих проблемах мало кто пишет а k8s сейчас везде.
Мое мненине, если вам нужен стриминг (особенно в двух напраляниях), то gprc это надежно и относительно просто. Но не надо ожидать что скорость вырастит в 2-10 раз показано на бенчмарках. Она может даже упасть.
а можно узнать по какой причине отказались от Thrift?
gRPC vs REST, что выбрать для нового сервера?