json rpc call failed как исправить
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-заголовках | — |
В теле запроса | В теле запроса |
Данные ответа могут быть: | |
---|---|
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, если нужен именно он. Теперь вы, по крайней мере, выберете его осознанно.
Hodlcoin json rpc fail? #77
Comments
Qwertylex commented Feb 3, 2018
The text was updated successfully, but these errors were encountered:
We are unable to convert the task to an issue at this time. Please try again.
The issue was successfully created but we are unable to update the comment at this time.
JayDDee commented Feb 4, 2018
As far as I know hodl doesn’t support getwork. As I recall there was a bounty to implement
it but it was never done. Do you know something I don’t?
Qwertylex commented Feb 4, 2018 •
Did you know optiminer’s hodlminer-wolf works just fine with hodlcoind?
If it isn’t using getwork, what is it using?
https://github.com/Optiminer/hodlminer-wolf
JayDDee commented Feb 5, 2018
Thanks for the info. I’ll look into it but it may take a while.
JayDDee commented Feb 7, 2018
I may have found the problem but I need your help testing it, I hope you compile from source.
I can’t test myself and the fix may not work or may break existing alogs so I can’t just release it.
It looks like hodl uses a new GBT block version number and the version test is failing causing the
miner to switch to getwork which apparently isn’t supported in the wallet.
I didn’t see any obvious other effects of the new version (just a quick scan) so simply increasing
the supported version may fix it.
If you can please make the following change to file cpu-miner.c at line 435, compile and restest:
old: #define BLOCK_VERSION_CURRENT 3
new: #define BLOCK_VERSION_CURRENT 4
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? Решать вам.
Искренне надеюсь, что я не потратил ваше время зря.
Json rpc call failed как исправить
Добрый день! Уважаемые читатели и гости одного из крупнейших IT блогов в рунете Pyatilistnik.org. В прошлый раз мы с вами разобрали замечательную утилиту командной строки robocopy, и с ее помощью научились создавать точные копии папок, двигать их в нужное расположение и многое другое. В сегодняшней публикации я покажу вам, как устранять ошибку «Сервер RPC недоступен (The rpc server is unavailable)», покажу примеры, когда ее мониторинг очень важен в работе корпоративных сервисов.
Для чего нужна служба «Удаленный вызов процедур (RPC)»
Процедура сообщения RPC
Когда программные операторы, использующие структуру RPC, компилируются в исполняемую программу, в скомпилированный код включается заглушка, которая выступает в качестве представителя кода удаленной процедуры. Когда программа запускается и выполняется вызов процедуры, заглушка получает запрос и пересылает его клиентской программе и времени выполнения на локальном компьютере. При первом вызове клиентской заглушки она связывается с сервером имен, чтобы определить транспортный адрес, по которому находится сервер.
Программа среды выполнения клиента знает, как обращаться к удаленному компьютеру и серверному приложению, и отправляет сообщение по сети, которое запрашивает удаленную процедуру. Точно так же сервер включает исполняющую программу и заглушку, которая взаимодействует с самой удаленной процедурой. Протоколы ответа-запроса возвращаются таким же образом.
Данная служба есть в любой операционной системе Windows, начиная от Windows 7 и заканчивая Windows 11 и в любой из Windows Server редакции.
Как работает RPC?
Когда вызывается служба RPC (удаленный вызов процедуры), вызывающая среда приостанавливается, параметры процедуры передаются по сети в среду, в которой должна выполняться процедура, а затем процедура выполняется в этой среде. Когда процедура завершается, результаты передаются обратно в вызывающую среду, где выполнение возобновляется, как если бы оно возвращалось из обычного вызова процедуры.
Во время RPC выполняются следующие шаги:
Если вы видите ошибку «Сервер RPC недоступен” (The RPC server is unavailable)», то у вас точно недоступен порт 135. Это может быть критичным для ряда ситуации. Например вы не сможете сохранить настройки RDS фермы, если у одного из хостов RDSH есть проблемы с RPC, то вы будите видеть ошибку «Could not change the connection state for server», вы не сможете перевести его в режим обслуживания (Drain Mode)
Или в приложении Terminal Services Manager будет ошибка при попытке получения данных «Сервер RPC недоступен«.
Так же RPC может быть причиной проблемы в репликации контроллеров домена, где в логах Windows будет фигурировать ошибка ID 1722. Это очень не приятный момент, который может привести к большим проблемам.
Типы RPC
Существует пять типов RPC:
Почему может не работать служба RPC
Преимущества удаленного вызова процедур
К преимуществам удаленного вызова процедур можно отнести следующее:
Недостатки RPC
Некоторые из недостатков RPC включают следующее:
Проверка доступности службы RPC
Если вдруг компьютер не ответил, то это не значит, что он не работает, может работать брандмауэр и просто блокировать ping пакеты.
Небольшой пример из практики, предположим, что вы мигрировали сервер в другую подсеть, в итоге в DNS должна быть изменена соответствующая запись, но Windows это поймет не сразу, так как у нее есть свой локальный кэш, он живет 15 минут, поэтому если при проверке DNS имени вам выдается не тот IP-адрес, вам необходимо произвести очистку кэша DNS.
Если удаленный RPC порт доступен вы в в строке TcpTestSucceeded будет стоять статус «True».
Если будет порт закрыт или блокируется, то ошибка «Сервер RPC недоступен (The rpc server is unavailable)» вам обеспечена. Поняв, что порт не отвечает, нужно удостовериться, что трафик от клиента до сервера не блокирует фаервол. По умолчанию в любой версии Windows есть встроенный брандмауэр. На время тестирования и поиска причины, я советую его выключить для всех профилей. Сделаем мы это через командную строку:
Данная команда выключит брандмауэр на всех трех профилях сетевой карты.
Далее если порт 135 стал доступен, то можно делать правила на удаленном сервере. Напоминаю, что нужно сделать правило для трех служб:
Еще хочу отметить, что если у вас есть сторонние антивирусные решения, например Касперский, то там так же есть встроенный сетевой экран, где так же нужно будет создать необходимые, разрешающие правила, которые корректно будут обрабатывать трафик динамических RPC портов.
Проверка работы служб RPC
Следующим шагом является проверка состояния службы на нужном вам сервере или компьютере. Проверять следует три службы:
В оболочке PowerShell выполните команду:
Для удаленного выполнения Enter-PSSession svt2019s01 далее Get-Service RpcSs,RpcEptMapper,DcomLaunch| Select DisplayName,Status,StartType
Напоминаю, что в команде svt2019s01, это имя удаленного сервера. Как видно из примера, все службы RPC запущены и имею автоматический тип запуска.
Если службы не запущены, то откройте оснастку «services.msc’, зайдите в свойства службы и выставите автозапуск и попробуйте запустить вручную.
Если по каким, то причинам вы не можете запустить службу из оснастки, то можно это сделать через реестр (Кстати реестр можно править и удаленно). Для этого есть несколько веток, но для начала откройте окно «Выполнить» и введите regedit.
В каждом из этих расположений есть ключик «Start«, выставите ему значение «2«, это будет означать автоматический запуск службы.
Дополнительные сетевые проверки
В некоторых случаях причиной ошибок с доступностью RPC выступает сбой на сетевых адаптерах. Помогает сброс сетевых настроек и перезагрузка. В сети с Active Directory, старайтесь, чтобы на всех ваших сетевых адаптерах в свойствах были выставлены обе галки IPV4 и IPV6, особенно это актуально для контроллеров домена, где вы легко можете получать ошибку 1722. Еще может помочь отключение протокола Teredo у IPv6. В командной строке выполните: