Всем приветы. А вы писали новый сервер с нуля? Какие технологии использовали? А рассматривали какие-либо варианты кроме старого доброго REST ? А что есть еще что-то ? С такими вопросами я когда-то пришел к своему лиду. Да, для меня было открытием, что можно использовать не только REST для обмена сообщениями между сервером и клиентом. Ах да, конечно я знал про SOAP, но использовать его уж очень не хотелось. Оказалось, что можно попробовать использовать Thrift или например gRPC. От Thrift пришлось отказаться по ряду причин, которые не сильно важны в данной статье. Кстати, возможно Thrift это именно то что вам нужно.
Так что же такое gRPC и в чем его отличие от, уже ставшего классическим, REST? Лучше ли gRPC? Может gRPC это снова хипстерская технология, которую все скоро забудут?
Не для кого ни секрет, что REST доминирует в современном мире API, особенно, когда речь идет о веб-приложениях и инфраструктурах, на основе микросервисов. Мало кто даже вспомнит, про то что микросервисы могут общаться по другому. Это наверное самый популярный ответ на собеседовании. Да если добавить еще feign клиента из Spring, то получается совсем красота и минимальные трудо затраты. Но для определенного набора сценариев использования, модель gRPC начала играть небольшую, но важную роль. Давайте попробуем разобраться, когда же нам стоит использовать REST, а когда gRPC.
Чтобы понять REST и gRPC, нам нужно начать с API (интерфейсов прикладного программирования). API-интерфейсы предоставляют правила и определения, которые позволяют приложениям обмениваться данными и взаимодействовать друг с другом. API определяет типы вызовов и запросов, которые одно приложение может отправлять другому, как выполнять эти запросы, используемые форматы данных и соглашения, которым должны следовать клиенты. API-интерфейсы также поддерживают «подключаемость» приложений, которые образуют более крупную систему, поскольку они позволяют двум приложениям - даже если они написаны на разных языках программирования и работают на разных платформах - общаться и взаимодействовать друг с другом. API-интерфейсы REST и API-интерфейсы gRPC относятся к различным архитектурным стилям для создания API-интерфейсов.
Про REST (передача репрезентативного состояния) API все знают: REST - это самый популярный архитектурный стиль для создания API-интерфейсов, особенно для веб-приложений и инфраструктур на основе микросервисов. REST определяет определенные ограничения и принципы, которые поддерживают взаимодействие между микросервисами и интернет-приложениями. Этим ограничениям и принципам разработчики могут следовать, а могут и не следовать. Хотя REST API может получать и возвращать сообщения, написанные в различных форматах, самым распространенным форматом, исходя из моего опыта, является JSON. JSON - это текстовый, удобный для чтения человеком формат, который является гибким, эффективным и не зависит от языка и платформы.
gRPC (удаленный вызов процедур Google): gRPC - это архитектура RPC с открытым исходным кодом, разработанная Google для обеспечения высокоскоростной связи между микросервисами. gRPC позволяет разработчикам интегрировать сервисы, написанные на разных языках. gRPC использует формат обмена сообщениями Protobuf (буферы протокола), который представляет собой высокоэффективный формат обмена сообщениями с высокой степенью упаковки для сериализации структурированных данных. Для некоторого набора сценариев использования gRPC API может быть более эффективным чем REST API (подробнее об этом позже).
Вот простая матрица, сравнивающая основы REST API и gRPC (картинка взята из интернета):
REST API и RPC API на примере микросервисов.
Думаю, что одним из лучших способов понять и пощупать тему API - это попытаться рассмотреть API в контексте разработки современных приложений, на основе микросервисов.
Что такое приложения на основе микросервисов?
Монолитное приложение содержит программирование всех своих сервисов и функций в единой неделимой кодовой базе, которая управляет всеми сервисами и функциями приложения. В то время как, приложения на основе микросервисов преодолевают самые большие ограничения традиционных монолитных приложений. Проблема в том, что по мере того, как разработчики подключают новые службы и функции к существующей структуре, становится все труднее изменять, обновлять и масштабировать приложение. Изменение одной части приложения может негативно повлиять на другие области. После многократного масштабирования, обновления и изменения монолита кодовая база в конечном итоге становится настолько взаимозависимой и трудной для понимания, что возникает необходимость перепроектировать всю систему с нуля.
Микросервисная архитектура решает эту проблему. Этот архитектурный стиль предполагает разбиение монолита на его компонентные службы и запуск каждого компонента как автономного приложения (называемого микросервисом). Затем эти отдельные микросервисы используют API-интерфейсы для взаимодействия друг с другом. Вместе эта группа микросервисов, подключенных к API, формирует большую архитектуру приложения. API-интерфейсы позволяют автономно работающим микросервисам, даже тем что написаны на разных языках и работают на разных платформах, создать подключаемую систему на основе компонентов. Очевидно, что обновление отдельных микросервисов происходит значительно быстрее и проще, поскольку изменения, которые вы вносите в автономно работающую службу, оказывают меньшее влияние на всю систему. Масштабирование проще и эффективнее, поскольку ресурсы могут быть перенаправлены на микросервисы, которые в этом нуждаются, в зависимости от требований использования. Более того, если один микросервис выйдет из строя или замедлится, вероятность выхода из строя всей инфраструктуры меньше. Все это приводит к созданию более эффективных, отказоустойчивых, масштабируемых и гибких систем, а API - это то, что делает все это возможным. Конечно можно оспорить преимущества микросервисов и найти множества примеров, когда монолит превосходит микросервисную архитектуру. Это огромная тема в которую сейчас нет смысла углубляться.
REST API
REST описывает организацию клиент-сервер, в которой внутренние данные предоставляются клиентам через формат обмена сообщениями JSON или XML. По словам Роя Филдинга, API квалифицируется как «RESTful», если соответствует следующим ограничениям:
Единый интерфейс: API должен предоставлять потребителям API определенные ресурсы приложения.
Независимость клиент-сервера: клиент и сервер работают независимо. Клиент будет знать только те URI, которые указывают на ресурсы приложения. Обычно они публикуются в документации API.
Без сохранения состояния: сервер не сохраняет данные, относящиеся к запросу клиента. Клиент сохраняет эти «данные состояния» на своем конце (через кеш).
Кэшируемые: ресурсы приложения, предоставляемые API, должны быть кэшируемыми.
Многоуровневая: архитектура является многоуровневой, что позволяет поддерживать различные компоненты на разных серверах.
Код по запросу (COD): это единственное необязательное ограничение REST. Это позволяет клиенту получать исполняемый код в качестве ответа от сервера. Другими словами, именно сервер определяет, как будут выполняться конкретные действия.
Наконец, архитектура REST API обычно опирается на протокол HTTP, а REST API являются наиболее распространенным форматом для создания веб-приложений и подключения микросервисов. Когда REST API становится общедоступным как веб-служба, каждый компонент (или услуга), предоставляемый веб-службой, представляется клиентам как ресурс. Клиенты могут получить доступ к этим ресурсам через общий интерфейс, который принимает различные HTTP-команды, такие как GET, POST, DELETE и PUT.
API RPC
Как предшественник REST, RPC (удаленный вызов процедур) представляет собой программную архитектуру, восходящую к 1970-м годам. RPC позволяет вызывать функцию на удаленном сервере в определенном формате и получать ответ в том же формате. Не имеет значения, какой формат использует сервер, выполняющий запрос, и не имеет значения, локальный это сервер или удаленный. RPC позволяет вызывать функцию на сервере и получать результат в том же формате.
Основная концепция RPC API аналогична концепции REST API. RPC API определяет правила взаимодействия и методы, которые клиент может использовать для взаимодействия с ним. Клиенты отправляют вызовы, которые используют «аргументы» для вызова этих методов. Однако в случае RPC API метод находится в URL-адресе. Аргументы, вызывающие методы, находятся в строке запроса. Чтобы проиллюстрировать это, вот как запрос RPC API сравнивается с запросом REST API:
RPC: запрос RPC API может использовать POST / deleteSmth и иметь строку запроса, которая говорит {"id": 777}
REST: запрос REST API записывает этот запрос как DELETE / smth / 777.
Погружение в API gRPC
Как вариант архитектуры RPC, gRPC был создан Google для ускорения передачи данных между микросервисами и другими системами, которым необходимо взаимодействовать друг с другом. По сравнению с REST API, gRPC API уникальны в следующих отношениях:
Протобуф (Protobuf) вместо JSON
Построен на HTTP 2 вместо HTTP 1.1
Создание собственного кода вместо использования сторонних инструментов, таких как Swagger
Передача сообщений в 7-10 раз быстрее
Более долгая имплементация и реализация, чем REST
Думаю, стоит детальнее разобрать каждое из этих различий между API REST и gRPC.
Protobuf вместо JSON / XML
И REST API, и RPC API отправляют и получают сообщения с использованием форматов обмена сообщениями JSON или XML. Они также могут использовать другие форматы, но наиболее распространены JSON и XML. Из них JSON стал самым популярным форматом, поскольку он гибкий, эффективный, платформенно-независимый и не зависит от языка. Он также основан на тексте и удобочитаем для человека, что упрощает работу операторам. Проблема в том, что для определенных случаев использования JSON недостаточно быстр или легковесен при передаче данных между системами.
В отличие от REST и RPC, gRPC преодолевает проблемы, связанные со скоростью и весом, и предлагает большую эффективность при передаче сообщений, используя формат обмена сообщениями Protobuf (буферы протокола). Вот несколько подробностей о Protobuf:
Независимость от платформы и языка, например JSON
Сериализует и десериализует структурированные данные для передачи в двоичном формате.
Поскольку он является сильно сжатым форматом, он не обеспечивает удобочитаемости JSON.
Ускоряет передачу данных, удаляя множество обязанностей, которыми управляет JSON, поэтому он может сосредоточиться исключительно на сериализации и десериализации данных.
Передача данных происходит быстрее, потому что Protobuf уменьшает размер сообщений и служит легким форматом обмена сообщениями.
Построен на HTTP 2 вместо HTTP 1.1
Еще один способ повышения эффективности gRPC - использование протокола HTTP 2.
API-интерфейсы REST обычно построены на HTTP 1.1, который использует модель взаимодействия запрос-ответ. Это означает, что когда микросервис получает несколько запросов от более чем одного клиента, он должен обслуживать их по одному, что замедляет работу всей системы. API REST также могут использовать HTTP 2, они по-прежнему ограничены моделью запрос-ответ и не используют поддержку HTTP 2 для двунаправленной потоковой связи.
В отличие от этого, gRPC использует HTTP 2 и пользуется преимуществами поддержки HTTP 2 как для взаимодействия с клиентом, так и для двунаправленной связи. Таким образом, gRPC может управлять «унарными» взаимодействиями, аналогичными HTTP 1.1 (когда клиент отправляет один запрос, а сервер отправляет один ответ). В то же время клиенты могут также открывать долговременные соединения, в которых каждый вызов RPC открывает новый поток HTTP 2, также известный как двунаправленная, «мультиплексируемая» или потоковая связь.
В HTTP 2, когда микросервис получает несколько запросов от более чем одного клиента, он достигает мультиплексирования, обслуживая множество запросов и ответов одновременно. В этом отношении API-интерфейсы gRPC отступают от ограничений API-интерфейсов REST в их способности непрерывно передавать информацию.
GRPC предоставляет три типа потоковой передачи:
На стороне сервера: клиент отправляет сообщение запроса на сервер. Сервер возвращает поток ответов клиенту. После завершения ответов сервер отправляет сообщение о состоянии (и в некоторых случаях конечные метаданные), что завершает процесс. После получения всех ответов клиент завершает свой процесс.
На стороне клиента: клиент отправляет поток сообщений запросов на сервер. Сервер возвращает один ответ клиенту. Он (обычно) отправляет ответ после получения всех запросов от клиента и сообщения о состоянии (и в некоторых случаях конечных метаданных).
Двунаправленный: клиент и сервер передают данные друг другу без особого порядка. Клиент - это тот, кто инициирует такой вид двунаправленной потоковой передачи. Клиент также завершает соединение.
Встроенная генерация кода вместо использования сторонних инструментов
Функции генерации кода встроены в gRPC через встроенный компилятор протоколов. При использовании REST API необходимо использовать сторонний инструмент, например Swagger, для автоматической генерации кода для вызовов API на разных языках.
Компилятор protoc, поставляемый с gRPC, совместим с широким спектром языков программирования. Это делает gRPC отличным средством для многоязычных сред, где вы подключаете множество различных микросервисов, написанных на разных языках и работающих на разных платформах.
Напротив, REST API не предлагает функций генерации собственного кода. Вы должны использовать сторонний инструмент, такой как Swagger, для генерации кода для вызовов API на разных языках. Это не доставляет неудобств, но стоит отметить, что gRPC не зависит от каких-либо внешних инструментов для генерации кода.
Передача сообщений в 7-10 раз быстрее
Согласно широко цитируемым тестам, опубликованным Руваном Фернандо, соединения gRPC API значительно быстрее, чем соединения REST API. Фактически, он сообщил, что они в 7-10 раз быстрее:
GRPC примерно в 7 раз быстрее REST при получении данных и примерно в 10 раз быстрее, чем REST при отправке данных для этой конкретной полезной нагрузки. В основном это связано с плотной упаковкой буферов протокола и использованием HTTP / 2 в gRPC
Вот результаты, которые получил Руван:
Более долгая реализация и имплементация, чем REST
Несмотря на преимущества в скорости передачи сообщений, реализация gRPC API намного медленнее, чем реализация REST API. По словам Руана Фернандо, внедрение простой службы gRPC занимает около 45 минут. Реализация веб-API или REST API занимает всего около 10 минут.
Фернандо сообщает, что дополнительное время внедрения отражает отсутствие встроенной поддержки gRPC в сторонних инструментах. Это в первую очередь потому, что gRPC еще не получил широкого распространения, особенно по сравнению с повсеместным распространением REST API. Вот что Фернандо говорит о времени внедрения gRPC:
Мне пришлось потратить примерно 45 минут на внедрение этой простой службы gRPC, из которых я потратил всего около 10 минут на создание WebAPI. В основном это связано с тем, что REST давно стал мейнстримом, и большинство основных фреймворков (например, ASP.NET Core MVC) имеют встроенную поддержку для быстрого развертывания таких сервисов (с помощью соглашений и шаблонов)
Когда лучше использовать REST или gRPC?
Давайте сравним, когда вам следует рассмотреть возможность использования REST API и gRPC API:
Когда использовать REST API
Независимо от того, создаете ли вы внутреннюю систему или открытую систему, которая предоставляет свои ресурсы остальному миру, REST API, вероятно, останутся фактическим выбором для интеграции приложений в течение очень долгого времени. Кроме того, REST API идеально подходят, когда системе требуется высокоскоростная итерация и стандартизация протокола HTTP. Благодаря универсальной поддержке сторонних инструментов REST API должны быть вашим первым аргументом в пользу интеграции приложений, интеграции микросервисов и разработки веб-сервисов.
Когда использовать API gRPC
Что касается gRPC, в большинстве сторонних инструментов по-прежнему отсутствуют встроенные функции для совместимости с gRPC. Таким образом, gRPC в основном используется для создания внутренних систем, то есть инфраструктуры, закрытой для внешних пользователей. С учетом этого предостережения, API-интерфейсы gRPC могут быть полезны в следующих случаях:
Соединения с микросервисами: связь с низкой задержкой и высокой пропускной способностью gRPC делает его особенно полезным для подключения архитектур, состоящих из легких микросервисов, где эффективность передачи сообщений имеет первостепенное значение.
Системы где используется несколько языков программирования: благодаря поддержке генерации собственного кода для широкого спектра языков разработки, gRPC отлично подходит для управления соединениями в среде с наличием нескольких языков.
Потоковая передача в реальном времени: когда требуется связь в реальном времени, способность gRPC управлять двунаправленной потоковой передачей позволяет вашей системе отправлять и получать сообщения в режиме реального времени, не дожидаясь ответа отдельного клиента.
Сети с низким энергопотреблением и низкой пропускной способностью: использование gRPC сериализованных сообщений Protobuf обеспечивает легкий обмен сообщениями, большую эффективность и скорость для сетей с ограниченным диапазоном пропускания и маломощных сетей (особенно по сравнению с JSON). Интернет вещей может быть примером такой сети, в которой могут быть полезны API gRPC.
Подведем итог о REST и gRPC
Из-за различных преимуществ API-интерфейсов gRPC, которые мы рассмотрели до сих пор, некоторые разработчики рассматривают gRPC как «будущее». Однако эти разработчики могут забегать вперед. gRPC еще не получил широкого распространения, и еще предстоит увидеть, будут ли его преимущества стимулировать более широкое распространение в будущем.
Для сравнения, REST поддерживается повсеместно, и практически каждая инфраструктура на основе микросервисов полностью зависит от API-интерфейсов REST как связующего звена, объединяющего их. Если ваш вариант использования не требует реализации gRPC, рисковать принятием gRPC на этом зарождающемся этапе (до широкого распространения) нецелесообразно и не нужно.