При разработке исходно облачных (cloud-native) приложений требуется наладить гладкую и эффективную коммуникацию между различными компонентами. Для начала давайте рассмотрим весь спектр инструментов от XML до gRPC, которые обеспечивают и улучшают эти критически важные взаимодействия.

XML (часто с применением SOAP):


<order>
    <bookID>12345</bookID>
    <quantity>2</quantity>
    <user>JohnDoe</user>
</order>


Достоинства

Строгая структура: структура XML обеспечивает единообразное форматирование данных. Например, имея 12345, можно быть уверенным, что в тегах заключён ID книги. В результате снижается степень неоднозначности при интерпретации данных.

Самодокументация: Теги описывают данные. Из записиJohnDoe чётко вычленяется имя пользователя, поэтому разработчикам становится проще понять данные, не обращаясь к дополнительной документации.

Недостатки

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

Синтаксический разбор может идти медленно: Для тех же 10 000 заказов системе потребуется разобрать каждый из открывающих и закрывающих тегов. Соответственно, на обработку такого кода тратится больше времени, чем на более лаконичные форматы.

JSON (обычно в сочетании с REST):


{
    "order": {
        "bookID": "12345",
        "quantity": 2,
        "user": "JohnDoe"
    }
}

Достоинства

Легковесный и удобочитаемый: этот формат лаконичный. Если бы у вас был массив из 10 000 заказов, то JSON обработал бы его без тех повторяющихмя тегов, которые мы видели в XML. Соответственно, данные получаются компактнее.

Поддерживается во многих языках: например, в JavaScript формат JSON поддерживается нативно. Модно преобразовать объект JSON в объект JavaScript при помощи простой функцииJSON.parse(), так обеспечивается бесшовная интеграция.

Недостатки

Нативно не поддерживает типы данных: в нашем примере "bookID": "12345" и "quantity": 2 выглядят по-разному, но JSON расценивает оба как текст. Из-за этого потенциально возможны баги, связанные с типизацией, либо может требоваться дополнительный синтаксический разбор.

Не встроена поддержка потоковой обработки: если вы хотите обновить цены книг в режиме реального времени, то JSON нативно не поддерживает такую операцию. Придётся искать окружные пути или прибегать к дополнительным технологиям.

GraphQL:


Запрос:

{
  order(id: "5678") {
    bookID
    user
  }
}

Ответ:

{
  "data": {
    "order": {
      "bookID": "12345",
      "user": "JohnDoe"
    }
  }
}

Достоинства

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

Всего одна конечная точка: не приходится управлять множеством конечных точек, например,/orders, /books и /users, достаточно управлять всего одной конечной точкой GraphQL. Благодаря этому вся серверная архитектура упрощается.

Недостатки

Издержки при синтаксическом разборе и обработке запросов: при каждом запросе серверу требуется интерпретировать данные и выбрать именно те, которые нужны. Если у вас миллионы запросов с варьирующимся содержанием, то нагрузка на сервер может оказаться чрезмерной.
При работе с простыми API такая технология — возможно, перебор: если вам требуются лишь простейшие операции CRUD то GraphQL при всей своей гибкости может привносить в систему дополнительную сложность.

gRPC:


Определение буферов протоколов:

message OrderRequest {
    string id = 1;
}

message OrderResponse {
    string bookID = 1;
    int32 quantity = 2;
}

service OrderService {
    rpc GetOrder(OrderRequest) returns (OrderResponse);
}

Достоинства

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

Поддержка двунаправленной потоковой передачи: представьте, что вам нужно в качестве фичи реализовать чат, в котором пользователи смогут обсуждать книги в режиме реального времени. При работе с gRPC мгновенный обмен сообщениями возможен и без постоянного опроса.
Сильная типизация: при int32 quantity = 2; вы можете быть уверены, что quantity — это всегда целое число. Поэтому уменьшается количество ошибок, связанных с типами.

Недостатки

Требуется изучить технологию буферов протоколов (Protocol Buffers): возможно, вашей команде разработчиков потребуется изучать новую технологию, поэтому на начальном этапе разработка потенциально может замедлиться.

Возможная непривычность: если команда привыкла работать с сервисами в стиле REST, то при переходе на gRPC команду ждёт крутая кривая обучения.

Переходим к основной теме.

Что такое gRPC?


Предположим, у вас два компьютера, которые должны обмениваться информацией. Компьютерам потребуется найти общий язык, точно, как и людям, говорящим на разных языках. Здесь gRPC напоминает выделенную телефонную линию, по которой компьютеры могут быстро и ясно общаться.

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

Аббревиатура gRPC, означающая «система вызова удалённых процедур от Google» — это телекоммуникационный фреймворк с открытым исходным кодом, обеспечивающий бесшовную коммуникацию между системами. По сути своей gRPC обеспечивает эффективную межпрограммную связь, в особенности, когда программы находятся на разных серверах или даже в разных ЦОД в глобальном масштабе.

Упрощённое руководство по gRPC

Допустим, у вас есть два друга, один из которых знает секретный рецепт (назовём его Повар), а второй хочет изучить этот рецепт (назовём его Ученик). Но есть проблема: они живут в разных городах. gRPC поход на волшебный телефон, по которому они могут переговариваться, но это ещё не всё. Ученик может следить за готовкой и осваивать рецепт так, как если бы он стоял прямо на кухне за плечом у Повара.

В мире компьютерных программ gRPC выполняет примерно такую же роль. Если вы написали приложение (оно в данном случае — Ученик), которое должно использовать функции или данные из программы или с другого компьютера (это Повар), то gRPC возьмёт на себя всю коммуникацию между ними.

Вот как это работает:

  1. Определяемся с меню: сначала сообщаете gRPC, какие блюда (или сервисы) вас интересуют, а также какие ингредиенты (параметры) для них нужны и что вы надеетесь увидеть на тарелке, которую будете подавать клиенту (возвращаемые типы).
  2. Повар готовит: на сервере (это кухня Повара), меню идёт в дело. Сервер готовит «блюда» именно так, как они описаны в рецепте и готов состряпать их, как только они потребуются.
  3. Волшебный телефон (gRPC): именно здесь gRPC вступает в игру в качестве телефонной линии между Учеником и Поваром. Это не простой телефон — по нему можно мгновенно передавать вкусы, запахи и информацию о поварских приёмах.
  4. Оформление заказа: Ученик (клиент) берёт копию меню (так называемую заглушку, но в этой статье проще считать, что это и есть «клиентское меню»), чтобы сделать заказ. В «клиентском меню» учтены все блюда, которые может приготовить повар и описано, как их запрашивать.
  5. Гурманство: как только Ученик позвонит по волшебному телефону и закажет блюдо, Повар приготовит это блюдо и отправит в ответ всё по тому же волшебному соединению. У Ученика складывается впечатление, как если бы это блюдо было приготовлено прямо у него на кухне.

С технической точки зрения gRPC — это канал, по которому организуется коммуникация между различными программными компонентами с разных машин, как если бы они были элементами одной и той же программы. Это технология для вызова удалённых процедур, при пользовании которой Ученик (клиент) вызывает метод у Повара (с сервера) как с локальной машины. Магия заключается в построении и соединении распределённых приложений, и при помощи gRPC этот процесс становится гораздо проще и интуитивнее.

Технические аспекты


Давайте подробнее рассмотрим технические аспекты.

Рассмотрим облачное приложение для сервиса доставки еды. Через это приложение пользователь хочет заказать блюдо из ресторана.

Буферы протоколов:

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

message FoodOrder {
    string dishName = 1;
    int32 quantity = 2;
    string specialInstructions = 3;
}

gRPC использует буферы протоколов (часто сокращается до «protobuf») в качестве основного механизма для определения сервисов и структуры информационных сообщений. Protobuf — это двоичный формат сериализации данных, более компактный и быстрый, чем традиционные текстовые форматы передачи данных, например, JSON или XML.

Потоковые возможности:

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

rpc OrderUpdates(string orderId) returns (stream StatusUpdate);

Без привязки к конкретному языку:

Пользовательское приложение может быть написано на Java (для Android) или на Swift (для iOS), а в системе ресторана используется Python. Благодаря тому, что gRPC поддерживает множество языков, в тот момент, когда от пользователя поступает заказ, обе системы гладко взаимодействуют, независимо от того, на каких языках они написаны.

Дедлайны/Задержки:

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

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

response = client.GetRestaurantList(timeout=3.0)

Дедлайн может быть указан как «текущий момент времени плюс длительность выполнения»:

Deadline deadline = Deadline.after(3, TimeUnit.SECONDS);
List<Restaurant> response = client.getRestaurantList(deadline);

Заключение


Мы познакомились с механизмом связи, который может очень пригодиться при разработке облачных приложений. Мы исследовали разные темы от структурированного XML до простого JSON, гибкого GraphQL и, наконец, эффективного gRPC. Каждый из этих инструментов играет ключевую роль, обеспечивая обмен информацией между приложениями в бескрайнем Интернете.

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

P.S Обращаем ваше внимание на то, что у нас на сайте проходит распродажа.

Комментарии (2)


  1. mentin
    24.07.2024 14:32
    +2

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


    1. petejones83
      24.07.2024 14:32
      +1

      Плюс, первая "проблема" json является проблемой xml: в json есть разница между числами и строками, а в xml как раз-таки нет.