json rpc что это

Подробнее о JSON RPC

Apr 7, 2019 · 3 min read

Не хочу разводить очередной холивар на эту тему. Поэтому, если вкратце, то GraphQL — это сложно, RPC — быстро, REST — некий медиум, но не хватает batch-запросов. И если у вас небольшое приложение или микросервис, то rpc, он же “вызов удаленной процедуры”, может оказаться гораздо лучше и экономичнее для вашей архитектуры, особенно если она основана на микросервисном подходе.

На моей практике это решение оказалось достаточно удобным и простым, но при этом мощным и расширяемым. И меня сильно удивило, что в мире node.js оно применяется крайне редко.

Су т ь подхода достаточно примитивна
Запрос включает в себя 4 поля:

Если вы не отправили id, то это означает, что ответ вас не интересует и от сервера вы ничего не получите. Такой вызов называется нотификацией.

Ответ может иметь следующие поля:

Вишенка на торте — это Batch-запрос!

Это означает, что мы можем слепить несколько отдельных ajax запросов в один и отдать его серверу в виде массива запросов. А при получении по заданным id мы поймем, на какой запрос получили ответ.

Небольшая тонкость!

Учтите, что по протоколу сервер не гарантирует последовательность элементов в ответе, например:

У нас имеется три основных объекта:

methods — наши JSON-RPC методы, функции которые реализуют основную логику. Это могут быть ваши контроллеры.

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

afterMethods (опционально) — хук, который по своей логике похож на предыдущий. Разница только в том, что он будет вызван после выполнения метода и в качестве второго параметра получит результат выполнения. Может быть удобен для логгирования запросов.

Также предоставлен callback (onError) — функция, в которую будет передана ошибка, если она случилась. Тут можно удобно подключить логгер ошибок вроде sentry.io.

Обратите внимание, что bodyParser вызван перед роутером. Можете использовать другой вариант парсинга тела запроса, главное, чтобы в req.body мы получили параметры запроса в формате JSONRPC.

Библиотека в стадии разработки, так что если у вас есть пожелания или идеи, смело пишите в комментариях или открывайте github issues.

Источник

Правильный JSON API или JSON RPC

Наверняка многие в курсе.

JSON — Текстовый формат обмена данными JSON
API — Программный интерфейс приложения API

Ключевые слова здесь: интерфейс обмена данными.

A, что же тогда JSON-RPC?

JSON — мы уже в курсе.

RPC — удаленный вызов процедур RPC

Приходим к выводу, что JSON-RPC это: удаленный обмен данными.

Наверняка этот обмен данными будет происходить с неким интерфейсом, т.е. с API.

И в чем проблема?! Спросите Вы. А в том, что некоторые программисты разрабатывая JSON API, т.е интерфейс, забывают про JSON-RPC.И начинается очередное изобретение велосипеда. Frontend программист говорит: «я передам тебе такой то json», а Backend программист отвечает: «а я тебе верну такой то json». И все бы ничего, но было бы хорошо вспомнить о том, что умные люди уже давно разработали стандарты, вернее протоколы обмена данными. И не какие то сверх сложные, а очень даже простые: JSON-RPC

Вероятно многие, если не сказать, что почти все, знают и даже пользуются этими протоколами. Написана куча серверов и т.д. Но вот лично меня не все устроило в существующих протоколах. Они показались мне не достаточно гибкими и не во всем логичными. Как вы уже догадались решил я изобрести свой велосипед json-rpc-1.5

Главные отличия от существующих протоколов это:

Получив кучу отрицательных комментариев и минусов, решил еще раз проверить, может я действительно, что то не так делаю? Естественно, всё что я здесь пишу, это мое личное мнение и я никому ничего не навязываю. Приведу пару примеров:
1. Пример запроса JSON API Yandex директ:

У них же можно почитать и про токены: Авторизационные токены

2. Пример из Сбербанк API Оплата из мобильного приложения с использованием Apple Pay
JSON запрос приводить не буду, он большой, по ссылке можно посмотреть.
Важно, что JSON запрос содержит «paymentToken». Вот ссылка на требования к формированию токена от Apple

Важно понимать, что токены и подписи в API используются часто, естественно на ряду с другими методами защиты. И те кто работает с разного рода API, прекрасно это знают.

Источник

REST? Возьмите тупой JSON-RPC

В последнее время на Хабре разгорелось много споров по поводу того, как правильно готовить REST API.

Вместо того, чтобы бушевать в комментариях, подумайте: а нужен ли вам REST вообще?
Что это — осознанный выбор или привычка?

Возможно, именно вашему проекту RPC-like API подойдет лучше?

Итак, что такое JSON-RPC 2.0?
Это простой stateless-протокол для создания API в стиле RPC (Remote Procedure Call).
Выглядит это обычно следующим образом.

У вас на сервере есть один единственный endpoint, который принимает запросы с телом вида:

И отдает ответы вида:

Если возникает ошибка — ответ об ошибке:

Бонусом поддерживаются batch-операции:

В поле id клиент API может отправлять что угодно, дабы после получения ответов от сервера сопоставить их с запросами.

Также клиент может отправлять «нотификации» — запросы без поля «id», которые не требуют ответа от сервера:

Библиотеки для клиента и сервера есть, наверное, под все популярные языки.
Если нет — не беда. Протокол настолько простой, что написать свою реализацию займет пару часов.

Работа с RPC-клиентом, который мне первым попался на npmjs.com, выглядит так:

Профиты

Согласованность с бизнес-логикой проекта

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

Есть предметные области, где операций в API должно быть больше чем сущностей.
Навскидку — проекты с непростыми бизнес-процессами, gamedev, мессенджеры и подобные realtime-штуки.

Да даже взять контентный проект вроде Хабра…

Нажатие кнопки «↑» под постом — это не изменение ресурса, а вызов целой цепочки событий, вплоть до выдачи автору поста значков или инвайтов.

Здесь также стоит упомянуть CQRS, с которым RPC-шный API будет смотреться лучше.

Во-вторых, кодов ответа в HTTP всегда меньше, чем типов ошибок бизнес-логики, которые вы бы хотели возвращать на клиент.

Кто-то всегда возвращает 200-ку, кто-то ломает голову, пытаясь сопоставить ошибки с HTTP-кодами.

В JSON-RPC весь диапазон integer — ваш.

JSON-RPC — стандарт, а не набор рекомендаций

Очень простой стандарт.

Данные запроса могут быть:
REST RPC
В URI запроса
В GET-параметрах
В HTTP-заголовках
В теле запроса В теле запроса
Читайте также:  ipoe что это в роутере

Данные ответа могут быть:
REST RPC
В HTTP-коде ответа
В HTTP-заголовках
В теле ответа (формат не стандартизирован) В теле ответа (формат стандартизирован)

Нет никаких best practices с форумов, есть стандарт.
Нет разногласий в команде, есть стандарт.

Конечно же, качественно реализованный REST API можно полностью задокументировать. Однако…

Знаете, что и где нужно передать в запросе к Github API, чтобы получить объект reactions вместе с issue?

Хорошо это или плохо? Решайте сами, гуглите сами. Стандарта нет.

Независимость от HTTP

В теории, принципы REST можно применять не только для API поверх HTTP.
На практике все по-другому.

JSON-RPC over HTTP безболезненно переносится на JSON-RPC over Websocket. Да хоть TCP.
Тело JSON-RPC запроса можно прямо в сыром виде бросить в очередь, чтобы обработать позже.

Больше нет проблем от размазывания бизнес-логики по транспортному уровню (HTTP).

HTTP 404
REST RPC
Ресурса с таким идентификатором нет
Здесь API нет Здесь API нет

JSON-RPC пригодится, если у вас есть:
— Batch-запросы
— Нотификации, которые можно обрабатывать асинхронно
— Вебсокеты

Не то, чтобы это все нельзя было сделать без JSON-RPC. Но с ним — чуть легче.

Подводные камни

Если вы собираетесь кешировать ответы вашего API на уровне HTTP — RPC может не подойти.
Обычно это бывает, если у вас публичное, преимущественно read-only API.
Что-то вроде получения прогноза погоды или курса валют.

Если ваше API более «динамичное» и предназначено для «внутреннего» использования — все ок.

Все запросы к JSON-RPC API в логах веб-сервера выглядят одинаково.
Решается логированием на уровне приложения.

Для JSON-RPC нет инструмента уровня swagger.io.
Подойдет apidocjs.com, но он гораздо скромнее.
Впрочем, документировать такой простой API можно хоть в markdown-файле.

«REST» — об архитектуре, а не глаголах HTTP — возразите вы. И будете правы.

В оригинальной диссертации Роя Филдинга не указано, какие именно глаголы, заголовки и коды HTTP нужно использовать.

Зато в ней есть волшебное слово, которое пригодится даже при проектировании RPC API. «Stateless».

Каждый запрос клиента к серверу должен содержать всю информацию, необходимую для выполнения этого запроса, без хранения какого-либо контекста на стороне сервера. Состояние сеанса целиком хранится на стороне клиента.

Делая RPC API поверх веб-сокетов, может возникнуть соблазн заставить сервер приложения хранить чуть больше данных о сессии клиента, чем нужно.

Насколько stateless должен быть API, чтобы не причинять проблем? Для контраста вспомним по-настоящему statefull протокол — FTP.

Клиент: [открывает TCP-соединение]
Сервер: 220 ProFTPD 1.3.1 Server (ProFTPD)
Клиент: USER anonymous
Сервер: 331 Anonymous login ok, send complete email address as your password
Клиент: PASS user@example.com
Сервер: 230 Anonymous access granted, restrictions apply
Клиент: CWD posts/latest
Сервер: 250 CWD command successful
Клиент: RETR rest_api.txt
Сервер: 150 Opening ASCII mode data connection for rest_api.txt (4321 bytes)
Сервер: 226 Transfer complete
Клиент: QUIT
Сервер: 221 Goodbye.

Состояние сеанса хранится на сервере. FTP-сервер помнит, что клиент уже прошел аутентификацию в начале сеанса, и помнит, в каком каталоге сейчас «находится» этот клиент.

Такой API сложно разрабатывать, дебажить и масштабировать. Не делайте так.

В итоге

Возьмите JSON-RPC 2.0, если решитесь сделать RPC API поверх HTTP или веб-сокетов.
Можете, конечно, придумать свой велосипед, но зачем?

Возьмите GraphQL, если он правда вам нужен.

Возьмите gRPC или что-то подобное для коммуникации между (микро)сервисами, если ваш ЯП это поддерживает.

Возьмите REST, если нужен именно он. Теперь вы, по крайней мере, выберете его осознанно.

Источник

JSON-RPC

Понравилась статья? Поделись:

JSON-RPC – протокол удаленного вызова процедур, который использует JSON (RFC 4627) в качестве формата данных. Данный протокол во многом похож на XML-RPC, спецификация определяет несколько типов данных и правила их обработки. JSON-RPC поддерживает уведомления и множественные вызовы, так как информация, приходящая на сервер не требует ответа. Он разработан, чтобы быть простым!

Содержание

История [ править ]

Первая версия протокола была представлена в 2005 году и по настоящий момент является официальной. В 2007 году вышло первое дополнение 1.1 WD, где были добавлены специфичные параметры, именованные коды ошибок и функции самонаблюдения. После были выпущены альтернативные соглашения 1.1 Alt и 1.1 Object Specification, также в 2007 году была выпущена версия 1.2, которая в дальнейшем была переименована в 2.0, добавлены именованные параметры и очередь вызовов. Последнее обновление было представлено в 2013 году.

Использование [ править ]

JSON-RPC производит отсылку запросов к серверу, реализующему удаленный протокол. Как клиент в большинстве случаев выступает программа, которой необходимо вызвать метод на удаленной системе. Входные параметры передаются в качестве массива или объекта, в некоторых случаях возможна передача выходных данных. Процесс осуществляется посредством отправки запроса на удаленный сервер через http или tcp/ip сокет. В случае http заголовок Content-Type определяется как application/json.

Особенности [ править ]

JSON-RPC 2.0 [ править ]

Условные обозначения [ править ]

Ключевые обозначения «MUST», «MUST NOT», «REQUIRED», «SHALL», «SHALL NOT», «SHOULD», «SHOULD NOT», «RECOMMENDED», «MAY», and «OPTIONAL» следует интерпретировать как в RFC 2119.

Поскольку JSON-RPC базируется на JSON, ему свойственен тот же тип системы (RFC 4627 ). В JSON могут быть реализованы четыре простых типа (string, Numbers, Booleans, и Null) и два структурированных типа (Objects и Arrays). Термин «Primitive» в этом описании ссылается на любой из этих четырех примитивных типов JSON. Термин «Structured» ссылается на структурированные типы JSON. В каждом случае, относящемуся к любому типу JSON, первая буква всегда будет заглавная: Object, Array, String, Number, Boolean, Null. True и False также всегда указываются с заглавной.

Все имена, передаваемые между Клиентом и Сервером, для любого типа данных, должны рассматриваться как чувствительные к регистру. Функцию терминов, способ и процедуру передачи могут считаться взаимозаменяемыми.

Клиент определяется как источник объектов Request и обработчик объектов Response. Сервер определяется как источник объектов Response и обработчик объектов Request. Одна из реализаций этой спецификации может легко выполнить обе эти роли, даже в случае одного или нескольких клиентов. Данная спецификация не учитывает уровень сложности.

Совместимость [ править ]

Объект запроса [ править ]

Вызов RPC представляется путем отправки объекта Request на сервер. Объект Request имеет следующие элементы:

jsonrpc Строка, указывающая версию протокола JSON-RPC должна быть записана в точности как «2.0».

method Строка, содержащая имя метода, который необходимо вызвать. Имена методов, начинающиеся со слова rpc, за которым следует символ периода (U + 002E или ASCII 46), зарезервированы для rpc-внутренних методов и расширений и НЕ ДОЛЖНЫ использоваться ни для чего другого.

Читайте также:  что делать если бурлит в животе на уроке

Params Структурированная переменная, содержащая значения параметров, которые будут использоваться во время вызова метода. Такой элемент МОЖЕТ быть опущен.

id Идентификатор, установленный Клиентом, который ДОЛЖЕН содержать значение String, Number или Null, если включен. Если он не включен, предполагается, что это уведомление. Значение ДОЛЖНО, как правило, не быть нулевым, а числа НЕ ДОЛЖНЫ содержать дробные части.

Сервер ДОЛЖЕН отвечать с тем же значением в объекте Response, если он включен. Этот элемент используется для корреляции контекста между двумя объектами. Использование Null в качестве значения для элемента id в объекте Request не рекомендуется, поскольку эта спецификация использует значение Null для ответов с неизвестным идентификатором. Помимо этого, поскольку JSON-RPC 1.0 использует значение id для Null для уведомлений, это может вызвать путаницу при обработке.

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

Уведомление [ править ]

Структуры параметров [ править ]

Если они присутствуют, параметры для вызова RPC ДОЛЖНЫ быть представлены как структурированные переменные. По позиции через массив либо по имени через объект. по позиции: params ДОЛЖНЫ быть массивом, содержащим значения в ожидаемом порядке сервера. по имени: params ДОЛЖЕН быть объектом, с именами участников, которые соответствуют именам ожидаемых параметров сервера. Отсутствие ожидаемых имен МОЖЕТ привести к генерированию ошибки. Имена ДОЛЖНЫ точно совпадать, включая случай, с ожидаемыми параметрами метода.

Объект ответа [ править ]

Когда выполняется вызов RPC, сервер ДОЛЖЕН отвечать как Response, за исключением случаев уведомлений. Ответ выражается как один объект JSON со следующими членами:

jsonrpc Строка, указывающая версию протокола JSON-RPC должна быть записана точно как «2.0».

result Этот элемент НЕОБХОДИМ для успеха. Этот элемент НЕ ДОЛЖЕН существовать, если возникла ошибка при вызове метода. Значение этого элемента определяется методом, вызываемым на сервере.

id Этот элемент НЕОБХОДИМ. Он ДОЛЖЕН быть таким же, как значение элемента id в объекте Request. Если при обнаружении идентификатора в объекте Request возникла ошибка (например, ошибка Parse / Invalid Request), она ДОЛЖНА быть Null. Любой элемент результата или элемент ошибки ДОЛЖЕН быть включен, но одновременно оба члена НЕ ДОЛЖНЫ быть включены.

Объект ошибки [ править ]

Когда вызов RPC встречает ошибку, объект ответа ДОЛЖЕН содержать элемент ошибки со значением, являющимся объектом со следующими элементами:

code Номер, указывающий тип ошибки, который произошел. Номер ДОЛЖЕН быть целым числом.

message Строка, содержащая краткое описание ошибки. Сообщение ДОЛЖНО быть ограничено кратким единственным предложением.

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

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

Batch [ править ]

Чтобы отправить несколько объектов Request одновременно, клиент может отправить массив, заполненный объектами Request.

Сервер должен ответить массивом, содержащим соответствующие объекты Response, после того, как все объекты запроса пакета были обработаны. Объект Response ДОЛЖЕН существовать для каждого объекта Request, за исключением тех, что НЕ ДОЛЖНЫ быть объектами Response для уведомлений. Сервер МОЖЕТ обрабатывать пакетный вызов RPC как набор одновременных задач, обрабатывая их в любом порядке и с любой шириной параллелизма.

Объекты Response, возвращаемые из пакетного вызова, могут быть возвращены в массиве в любом порядке. Клиент ДОЛЖЕН соответствовать контексту между набором объектов Request и результирующим набором объектов Response на основе элемента id в каждом объекте.

Если сам вызов пакета rpc не может быть признан допустимым JSON или как массив с хотя бы одним значением, ответ от сервера ДОЛЖЕН быть единственным объектом Response. Если в массиве Response отсутствуют объекты Response, которые должны быть отправлены клиенту, сервер НЕ ДОЛЖЕН возвращать пустой массив, в таком случае он ничего не должен возвращать.

Расширения [ править ]

Имена методов, начинающиеся с rpc. зарезервированы для системных расширений и НЕ ДОЛЖНЫ использоваться ни для чего другого. Каждое расширение системы определено в соответствующей спецификации. Все расширения системы являются ДОПОЛНИТЕЛЬНЫМИ.

Источник

JSON-RPC? Возьмите хитрый REST

Уверен, что заголовок вызвал здоровую реакцию — “ну опять началось…” Но позвольте завладеть вашим вниманием на 5-10 минут, и я постараюсь не обмануть ожидания.

Структура статьи будет такова: берется стереотипное утверждение и раскрывается “природа” возникновения этого стереотипа. Надеюсь, это позволит взглянуть на выбор парадигмы обмена данными в ваших проектах под новым углом.

Для того, чтобы была ясность в том, что такое RPC, предлагаю рассматривать стандарт JSON-RPC 2.0. C REST ясности нет. И не должно быть. Все, что нужно знать о REST — он неотличим от HTTP.

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

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

Действительно, если у вас будет всего одна нода backend, это будет казаться быстрее при batch-запросе. Потому, что три REST запроса потребуют в три раза больше ресурсов от одной ноды на установку соединений.

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

Но такие инфраструктуры можно встретить, разве что, в in-house решениях и Enterprise. В крайнем случае, в небольших WEB проектах. А вот полноценные WEB решения, да еще и именуемые HighLoad так строить не стоит. Их инфраструктура должна отвечать критериям высокой доступности и нагруженности. И картина меняется.

Зеленым отмечены каналы активности инфраструктуры при том же сценарии. Обратите внимание, как ведет себя RPC теперь. Запрос использует инфраструктуру только по одному плечу от балансировщика к backend. В то время, как REST все также проигрывает в первом запросе, но наверстывает упущенное используя всю инфраструктуру.

Достаточно в сценарий ввести не два запроса на обогащение, а, скажем, пять или десять… и ответ на вопрос “кто выигрывает теперь?” становится неочевиден.

Предлагаю глянуть еще шире на проблему. На схеме видно, как используются каналы инфраструктуры, но инфраструктура не ограничивается каналами. Важной составляющей высоконагруженной инфраструктуры являются кэши. Давайте теперь получим какой-то артефакт пользователя. Несколько раз. Скажем 32 раза.

Посмотрите, как заметно “поправилась” инфраструктура на RPC для того, чтобы отвечать требованиям высокой нагрузки. Все дело в том, что REST использует всю мощь HTTP протокола в отличие от RPC. На приведенной схеме эта мощь реализуется через метод запроса — GET.

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

Читайте также:  что делать если вантуз не помогает

Следовательно, RPC не в состоянии эффективно использовать инфраструктурные кэши. Это приводит к тому, что приходится “завозить” софтовые кэши. На схеме в этой роли представлен Redis. Софтовый кэш, в свою очередь, требует от разработчика дополнительный кодовый слой и заметные изменения в архитектуре.

Давайте теперь посчитаем, сколько же запросов “родил” REST и RPC в рассматриваемой инфраструктуре?

Запросы Входящие к backend к СУБД к софт-кэшу (Redis) ИТОГО
REST 1/32* 1 1 0 3 / 35
RPC 32 32 1 31 96

[*] в лучшем случае (если локальный кэш используется) 1 запрос (один!), в худшем 32 входящих запроса.

В сравнении с первой схемой разница разительная. Теперь становится очевидным выигрыш REST. Но предлагаю не останавливаться на достигнутом. Развитая инфраструктура включает в себя CDN. Часто он же решает вопрос противодействия DDoS и DoS атакам. Получим:

Тут для RPC все становится совсем плачевно. RPC просто не в состоянии делегировать работу с нагрузкой CDN. Остается надеяться только на системы противодействия атакам.

Можно ли на этом закончить? И опять, нет. Методы HTTP, как выше уже говорилось, имеют свою “магию”. И неспроста метод GET является тотально используемым в Internet. Обратите внимание на то, что этот метод способен обращаться к части контента, способен ставить условия, которые смогут интерпретировать инфраструктурные элементы еще до передачи управления вашему коду и т.д. Все это позволяет создавать гибкие, управляемые инфраструктуры, способные переваривать действительно большие потоки запросов. А в RPC этот метод… игнорируется.

Так почему так устойчив миф о том, что batch запросы (RPC) быстрее? Лично мне кажется, что большинство проектов просто не достигают такого уровня развития, когда REST способен показать свою силу. Более того, в небольших проектах, он охотнее показывает свою слабость.

Выбор REST или RPC это не волевой выбор отдельного человека в проекте. Этот выбор должен отвечать требованиям проекта. Если проект способен выжать из REST все то, что он действительно может, и это действительно нужно, то REST будет отличным выбором.

Но если на то, чтобы получить все профиты REST, нужно будет нанять в проект девопсов, для оперативного масштабирования инфраструктуры, админов для управления инфраструктурой, архитектора для проектирования всех слоев WEB сервиса… а проект, при этом, продает три пачки маргарина в день… я бы остановился на RPC, т.к. этот протокол более утилитарный. Он не потребует глубоких знаний работы кэшей и инфраструктуры, а сфокусирует разработчика на простых и понятных вызовах нужных ему процедур. Бизнес будет доволен.

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

Это свойство RPC является несомненным плюсом, т.к. легко удерживать БД в консистентном состоянии. А вот с REST выходит все сложнее. Запросы могут приходить непоследовательно на разные ноды backend.

Этот “недостаток” REST является обратной стороной его преимущества описанного выше — способность эффективно использовать все ресурсы инфраструктуры. Если инфраструктура спроектирована плохо, а тем более, если спроектирована плохо архитектура проекта и БД в частности, то это действительно большая боль.

Но так ли надежны batch-запросы как кажутся? Давайте рассмотрим кейс: создаем пользователя, обогащаем его профиль каким-то описанием и отсылаем ему SMS с секретом для завершения регистрации. Т.е. три вызова в одном batch-запросе.

Рассмотрим схему. На ней представлена инфраструктура с элементами высокой доступности. Есть два независимых канала связи с SMS шлюзами. Но… что мы видим? При отправке SMS возникает ошибка 503 — сервис временно недоступен. Т.к. отправка SMS упакована в batch-запрос, то весь запрос должен откатиться. Действия в СУБД аннулируются. Клиент получает ошибку.

Следующая попытка — лотерея. Либо запрос опять попадет на ту же ноду и опять вернет ошибку, либо повезет, и он выполнится. Но главное, что как минимум один раз наша инфраструктура уже потрудилась зря. Нагрузка была, а профита нет.

Хорошо, давайте представим, что мы напряглись (!) и продумали вариант, когда запрос может успешно выполниться частично. А остаток, мы вновь попытаемся выполнить через какой-то интервал времени (Какой? Решает фронт?). Но лотерея так и осталась. Запрос на отправку SMS с вероятностью 50/50 вновь провалится.

Согласитесь, со стороны клиента, сервис не кажется таким надежным как хотелось бы… а что REST?

REST опять использует “магию” HTTP, но теперь с кодами ответов. При возникновении ошибки 503 на SMS шлюзе, backend транслирует эту ошибку балансировщику. Балансировщик получая эту ошибку, и не разрывая соединение с клиентом направляет запрос на другую ноду, которая успешно отрабатывает запрос. Т.е. клиент получает ожидаемый результат, а инфраструктура подтверждает свое высокое звание “восокодоступной”. Пользователь счастлив.

И опять это не все. Балансировщик не просто получил код ответа 503. Этот код при ответе, по стандарту, желательно снабдить заголовком “Retry-After». Заголовок дает понять балансировщику, что не стоит беспокоить эту ноду по этому роуту в течении заданного времени. И следующие запросы на отправку SMS будут направляться сразу на ноду, у которой нет проблем с SMS шлюзом.

Как мы видим, надежность JSON-RPC переоценена. Действительно, легче организовать консистентность в БД. Но жертвой, в таком случае, станет надежность системы в целом.

Вывод во многом аналогичен предыдущему. Когда инфраструктура проста, очевидность JSON-RPC несомненно его плюс. Если проект предполагает высокую доступность с высокой нагруженностью, REST смотрится более верным, хотя и более сложным решением.

Порог входа в REST ниже

Я думаю, что выше проведенный анализ, развенчивающий устоявшиеся стереотипы о RPC наглядно показал, что порог входа в REST несомненно выше, чем в RPC. Связанно это с необходимостью глубокого понимания работы HTTP, а также, с необходимостью обладать достаточными знаниями о существующих инфраструктурных элементах, которые можно и нужно применять в WEB проектах.

Так почему многие думают, что REST попроще будет? Лично мое мнение заключается в том, что эта кажущаяся простота исходит из самих манифестов REST. Т.е. REST это не протокол, а концепция… у REST нет стандарта, есть некоторые рекомендации… REST не сложнее HTTP. Кажущаяся свобода и анархия манит “свободных художников”.

Несомненно, REST не сложнее HTTP. Но сам HTTP это хорошо продуманный протокол, который доказал свою состоятельность десятилетиями. Если нет глубокого понимания самого HTTP, то и о REST судить нельзя.

А вот о RPC — можно. Достаточно взять его спецификацию. Так нужен ли вам тупой JSON-RPC? Или все же хитрый REST? Решать вам.

Искренне надеюсь, что я не потратил ваше время зря.

Источник

Сказочный портал