Skip to main content

Текстовые RPC: JSON-RPC, SOAP, GraphQL

RPC-стиль API

RPC (Remote Procedure Call) — стиль API, при котором клиент вызывает функцию (метод) на удалённом сервере, передавая параметры и получая результат. В отличие от REST, где в центре внимания ресурсы и глаголы HTTP, в RPC в центре внимания действие (вызов метода).

RPC-стиль можно разделить на две большие группы:

  • Текстовые (небинарные) RPC — протоколы, использующие текстовые форматы (JSON, XML) для передачи данных.
  • Бинарные RPC — протоколы, использующие бинарные форматы сериализации (например, gRPC).

Текстовые RPC

Текстовые RPC — это протоколы, которые используют текстовые форматы для представления запросов и ответов: JSON, XML и другие.

Отсутствие привязки к конкретному формату и транспорту — их ключевое свойство. Они могут работать поверх HTTP, WebSocket, очередей сообщений и т. д., что делает их гибкими для разных сценариев интеграции.

К типичным представителям текстовых RPC относятся:

  • JSON-RPC
  • SOAP (и его предшественник XML-RPC)
  • GraphQL — с некоторыми оговорками его тоже относят к этой группе.

JSON-RPC

Image

JSON-RPC — это протокол, который описывает, как передавать запросы и ответы в формате JSON.

Структура запроса. При работе поверх HTTP используется один и тот же endpoint и один глагол (обычно POST). Всё, что нужно для вызова, указывается внутри тела запроса:

  • jsonrpc — версия протокола (обязательное поле).
  • method — имя вызываемой функции (любое, не привязано к HTTP-глаголам: createUser, likePost, delete и т. д.).
  • params — параметры вызова (JSON-объект или массив).
  • id — идентификатор запроса, чтобы сопоставить его с ответом.

Структура ответа. Ответ содержит те же поля:

  • jsonrpc — версия протокола.
  • result — результат выполнения (при успехе).
  • error — объект ошибки (при неудаче), с собственным кодом и сообщением.
  • id — тот же идентификатор, что был в запросе.

Важно: при успехе и при ошибке HTTP-статус-код может быть один и тот же (200). Ответ об ошибке передаётся внутри тела JSON, а не через статус-код HTTP. Это сделано сознательно — чтобы не привязываться к HTTP.

Ключевое свойство: независимость от транспорта. Главная особенность JSON-RPC (и других текстовых RPC) — отсутствие привязки к конкретному транспортному протоколу. Поскольку вся значимая информация (метод, параметры, идентификатор) находится внутри тела запроса, а не в HTTP-глаголе или endpoint'е, такой протокол можно без изменений «переложить» на другой транспорт:

  • Сегодня — поверх HTTP.
  • Завтра — поверх WebSocket.
  • Послезавтра — поверх очередей сообщений.

Меняется только способ доставки, сама логика вызова остаётся неизменной.


SOAP

Image

SOAP (Simple Object Access Protocol) — ещё один представитель текстовых RPC. Идейно он похож на JSON-RPC, но использует XML в качестве формата сообщений.

Как и в JSON-RPC, используется один и тот же endpoint и один глагол (POST). Запрос и ответ вкладываются в тело HTTP-сообщения в виде XML-конверта. Внутри этого конверта, на уровне самого SOAP-протокола, передаётся вся необходимая информация:

  • Какую функцию (метод) вызываем.
  • Параметры вызова.
  • Собственные заголовки (SOAP-headers) — структура которых строго описана в рамках протокола.

SOAP, как и JSON-RPC, не привязан к HTTP. Он может работать поверх любых транспортных протоколов — включая брокеры сообщений (JMS, AMQP и т. д.). Именно это свойство делало SOAP популярным в корпоративной среде (ESB, банки, крупный enterprise) в 2000–2010-х годах: SOAP-сервисы могли общаться напрямую через шины сообщений, не будучи привязанными к HTTP.


GraphQL

Image

Отнесение GraphQL к RPC-стилю — холиварная тема, но спикер последовательно относит его к текстовым RPC, поскольку GraphQL, как и JSON-RPC с SOAP, формально не привязан к транспорту, хотя на практике почти всегда работает поверх HTTP.

Если смотреть на GraphQL как на протокол уровня L7+, он определяет три типа операций:

  1. Query — запросы на получение данных (аналог GET).
  2. Mutation — запросы на изменение данных (создание, обновление, удаление).
  3. Subscription — подписка на события от сервера (реализуется поверх WebSocket или SSE).

Первые две операции — это классический request-response (запрос и ответ передаются в теле HTTP). Subscription используется реже и даёт серверу возможность самому инициировать отправку данных.

Ключевая особенность: клиент управляет ответом. В REST каждый объект или коллекция требует отдельного endpoint'а. В GraphQL клиент сам в запросе указывает, какие объекты и какие их атрибуты он хочет получить.

Пример:

query {
pets {
name
species
}
}

Сервер возвращает ровно то, что запросили. Если из запроса убрать species, ответ будет содержать только name. Если добавить id или photo — появятся и они.

Ответ укладывается в обычное HTTP body (JSON). Это и есть то, что маркетингово называют «языком запросов» — хотя технически это просто протокол, где структура ответа определяется запросом.

GraphQL — не только протокол. Помимо транспортного протокола, GraphQL включает в себя:

  • Семантику описания данных (схемы, типы, связи).
  • Архитектурный паттерн или фреймворк — сервер (или GraphQL gateway), который принимает запросы, собирает данные из разных источников (REST, другие GraphQL-сервисы, SOAP, базы данных) и формирует единый ответ.

Один из самых популярных фреймворков для этого — Apollo.

Независимость от транспорта. Как и другие текстовые RPC, GraphQL не привязан к HTTP. Теоретически его можно использовать поверх WebSocket, очередей сообщений и т. д. — вся значимая информация находится в теле запроса, а не в HTTP-глаголах или endpoint'ах. Однако на практике его почти всегда используют поверх HTTP.