Как стать автором
Обновить

Комментарии 29

У меня вопрос к руководителю SpaceWeb: Ну поставили вы джуна руководить разработкой, бывает, но зачем позориться-то на весь интернет?

Человек же совершенно не понимает, что такое рест и что он к протоколу, никаким боком не привязан (у нас, например, рест апи единообразно работает поверх http, websocket, sse и даже webrtc); не способен сделать тривиальный фасад к апи, без отдельных роутингов для каждого метода; просто взял первый попавшийся кривой фремворк (fastapi) и сделал поверхностные выводы об архитектурном принципе (rest); даже не рассмотрел ни graphql, ни odata, ни даже harp (про решаемые ими проблемы, очевидно, даже не в курсе, так что ждите в скором времени костылей); высасывает из пальца разницу в необходимости описывать входящие и исходящие типы, которой на самом деле нет (более того, в ресте типов надо описывать меньше, так как число ресурсов кратно меньше числа методов в эквивалентном рпц, а валидация и интроспекция нужна в обоих случаях и в обоих же случаях может быть автоматизирована).

Понимаю, звучит обидно, но вас же дети читают - чему вы их учите? Что достаточно взять 2 самых популярных среди хомячков решения, проигнорировав все остальные достижения человечества, провести поверхностный анализ, наговорить глупостей, выбрать посредственное решение и пустить его в прод?

Доброго вечера!

GraphQL — язык запросов, а не архитектурный стиль. Это тоже и управление, и передача состояния — но в статье мы пишем несколько о другом: здесь мы сравниваем только классический RESTful API и JSON-RPC 2.0. Сравнивать всё со всем (если мы правильно понимаем, что вы предлагаете) — это объём материала на несколько книг, а не одну статью на Хабре.

RESTful API — архитектура, которая базируется на HTTP, а все остальные, как вы выражаетесь, «элементарные фасады» — как раз и есть ресурсы, которые мы бы тратили на доработку там, где JSON-RPC работает из коробки.

Ваше утверждение о том, что Django и FastAPI — это «кривые фреймворки», мягко говоря, не выдерживает критики.

В остальном спасибо за внимание и желаем хорошего дня!

Спасибо за ссылку на документацию! Открываем её и видим утверждение:

"…REST does not restrict communication to a particular protocol…"

И оно верное, но с оговоркой, которая следует дальше:

"…but it does constrain the interface between components…"

Чуть выше, в разделе 5.2.2, как раз и упоминается одно из таких ограничений:

"…From an abstract viewpoint the invocation is synchronous, but both in and out-parameters can be passed as data streams…"

, из-за которого в классическом REST, в отличие от JSON-RPC, вы не сможете сделать асинхронное взаимодействие с ресурсами даже при выборе транспорта, отличного от HTTP. Разумеется, асинхронное взаимодействие можно сделать для своей реализации, но для этой технологии это будет костыль, тогда как в JSON-RPC это будет работать нативно.

Гляжу в книгу и вижу фигу..

Интерфейс соединителя аналогичен процедурному вызову (RPC), но с важными отличиями в передаче параметров и результатов. Входящие параметры состоят из данных управления запросом, идентификатора ресурса, указывающего цель запроса, и необязательного представления. Выходные параметры состоят из данных управления ответом, необязательных метаданных ресурсов и необязательного представления. С абстрактной точки зрения вызов является синхронным, но как входные, так и выходные параметры могут передаваться как потоки данных. Другими словами, обработка может быть запущена до того, как значение параметров будет полностью известно, что позволяет избежать задержки при пакетной обработке больших передач данных. (то есть получать запрос и выдавать ответ можно асинхронно, в отличие от RPC, которому нужен весь запрос до вызова, а ответ будет только по его окончанию)

Гляжу в книгу и вижу фигу..

То, что запрос начал обрабатываться раньше, чем были переданы все его параметры, не делает запрос асинхронным.

Клиент в любом случае будет ждать начала передачи ответа или его части для начала обработки (даже если это потоковая передача данных). И, как правило, проблема совсем не в длительной отправке запроса, а в длительном ожидании начала ответа (пока работает бизнес-логика). В этом случае передача данных потоком никак вам не поможет.

кривой фремворк (fastapi)

Пруфы?

Пруфы в статье:

  • Необходимость писать роуты для каждого метода.

  • Прибитость гвоздями к хттп.

Буду надеяться, что ты все таки нежно стебешь

Ну то есть и в этом автор наврал? graphql тоже кривой так-то.

Весьма относительное мнение, я бы сказал сверхредкое

Скорее слишком «голый», имхо.

не способен сделать тривиальный фасад к апи

Можете по поводу фасада к апи поподробнее ответить? Я не понял как фасад к апи решает проблему написания множества обработчиков роутов в REST.

Например есть 10 классов, в каждом по 3 метода: добавить, изменить, удалить. Итого 30 методов к которым может обратиться каждый клиент API.

Автор статьи пишет, что для RESTful мы должны будем прописать в коде все 30 роутов, а для JSON-RPC всего 10. Вы пишите, что нужно просто сделать фасад к апи, а не прописывать роут для каждого из 30 методов. Как вы предлагаете используя фасад к апи устранить необходимость прописывания 30 роутов?

Спасибо за ссылку на пример, он уместен. Но нет ли такого, что вы превратили REST в PRC, который обслуживает 4 метода: GET, POST, PUT и DELETE?

В это и суть реста как бы - ограниченный набор методов для работы с неограниченным набором ресурсов.

Эммм...
Вы пишете, что в Rest "Нужен роутинг для каждого метода", но так и json-rpc нужны. И в своем примере вы итерируясь по методам класса Users, создаете их. а потом в этих хендлерах уже занимаетесь валидаций реквестов и вызовом бизнес логики.

В ресте "Продумываем формат параметров и возвращаемых значений для каждого вызова API". Молю Бога, чтобы вы и json-rpc продумывали, что вы от кого получаете и что кому отдаете.

В ресте "При необходимости управляем кодами ответов HTTP", ну так json-rpc вам нужно будет управлять кодами ответов json-rpc.

и вывод по ресту: "тратим время на разработку не только бизнес-логики, но и на разработку методов для API" - ну так вы делаете все тоже самое, только придумали себе другие названия.

Возможно, в вашем случае json-rpc и хороший выбор, но даже если этот выбор правильный, вы пришли к нему неправильным путем

Блин, я выводы по статье дочитал..

Серьезно?? вы увеличили количество клиентов использующих АПИ из-за перехода на json-rpc?? сходите в grpc - еще в 6 раз вырастет..

У вас получилось писать асинхронно и увеличить в 2 раза количество запросов за счет смены rest - json-rpc.. Это прям вау, это достояно доклада по computer science.

Запустили генератор документации на ReactJS.


Тут вообще молодцы, вместо того, чтобы из коробки использовать openapi, написали свое.. Всегда свой костыль ближе и приятнее..

Сократили разворачивание API для новых серверов в 4 раза.


У вас до json-rpc - инженер лично выезжал в дата центр к серверу?

Простите, конечно, я просто вообще не понимаю, как связаны выводы со всем, что описано..


Спасибо за развёрнутое мнение! Сложилось впечатление, что вы смотрите на RPC через призму REST и потому не придаёте значения некоторым различиям (а они есть).

Так, в случае RPC класс Users — это не handler, а бизнес-логика. Метод, добавленный в класс, автоматически будет доступен в API (и, например, для повторного использования в проекте). Создав метод нативными средствами языка, вы избавляетесь от необходимости делать что-то для API: RPC-сервер проверит корректность вызова метода и переданных параметров, и в случае некорректного вызова сам вернет ошибку без вашего участия. Разумеется, не стоит путать проверку корректности вызова и валидацию или санацию входных данных. Эта часть будет при любой выбранной архитектуре.

P.S. ваш совет о gRPC хорош и разумен, но эта технология тяжело встает на legacy-проект (у нас именно этот случай). Хотя, очень вероятно, в будущем мы как раз на gRPC и перейдем.

нет, не смотрю в контексте REST. Чаще использую GRPC на проектах, поэтому скорее смотрю через призму GRPC.

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

Ну и самое главное, как вы формируете "роутер":

@Request.application
def application(request):
     users = Users() # класс к которому открываем доступ
     method_list = inspect.getmembers(users, predicate=inspect.isfunction)
      for method in method_list:
            # диспетчер методов {<method_name>: callable}
            dispatcher[method[0]] = method[1]
response = JSONRPCResponseManager.handle(
       request.data, dispatcher)

Ваши методы из класса users вызываются функцией handle.. Это именно хендлер.. Если вы туда еще и бизнес логику прикладываете, то зря, но зависит от размера сервиса, если на пару хендлеров - то ну и пусть будет, а если на как минимум десять, то точно зря)

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

Пруфы и подробности — в самом коде JSONRPCResponseManager: https://github.com/pavlov99/json-rpc/blob/master/jsonrpc/manager.py

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

Вы где валидируете реквесты? нигде? Вы где форматируете ответ?

Given dispatcher it handles
request (both single and batch) and handles errors.

"Хендлером" - является диспатчер, который вы сконфигурировали итерацией по методам класса. Фактически итерацией сделали роутер из вашего примера с фастапи.. То есть класс Users - и есть класс с хендлерами..

То же самое можно в фастапи сделать класс, в него поместить все хендлеры, потом пробежаться по методам класса и router.add_api_route добавить хендлеры в роутер.

Вы реально не видите, что это одно и то же?

Хотя, вероятно, вы следите, как растет количество пользователей от смены реста на json-rpc со своими костылями..

Спасибо за развернутый ответ, и мы рады, что получается конструктивная дискуссия, но все же вы вырвали из контекста описание метода JSONRPCResponseManager.handle. Вот как звучит его полное описание:

Method brings syntactic sugar into library. Given dispatcher it handles
request (both single and batch) and handles errors.
Request could be handled in parallel, it is server responsibility.

что в дословном переводе

Метод добавляет синтаксический сахар в библиотеку. Учитывая диспетчер, он обрабатывает запрос (как одиночный, так и пакетный) и обрабатывает ошибки. Запрос может обрабатываться параллельно, это ответственность сервера.

Этот метод принимает запрос, валидирует его на предмет корректности JSON-RPC, вызывает метод handle_request, который, собственно, и отправляет его в бизнес-логику (dispatcher), принимает ответ от бизнес-логики, форматирует ответ по спецификации JSON-RPC и возвращает респонс. Именно это определение для хэндлера вы и дали.

Возможно, вы путаете валидацию запроса (некорректный запрос, вызов несуществующего метода или ошибку в параметрах и т. п.) и валидацию непосредственно параметров, с которыми вызывается удаленный метод (а такую валидацию, как мы писали ранее, необходимо делать при выборе любой технологии)

Что касается предложения "сделать класс, в него поместить все хендлеры, потом пробежаться по методам класса и router.add_api_route добавить хендлеры в роутер" — так это как раз и есть RPC, который сделали для FastAPI. На самом деле, технологии REST и RPC очень близки, особенно когда часть технологии RPC интегрируют в классический REST. Но это и есть костыли к REST.

Ну ок, считайте, что хендлеров у вас нет, есть только бизнес логика)

О этот мир иллюзий и грез.. Вот вам идея следующей статьи - "мы переименовали X в Y и повысили производительность разработчиков на 5000000000000000000000000%".

Что-то руководитель трех рандомных символов уже не в первой базу выдает, мм)

Живет в иллюзиях, не знает иных технологий, сравнивает две архитектуры не по их начинке, а по тому как он ендпоинт создает, серьезно?

Когда HTTP стал протоколом транспортного уровня?

Это как так вышло, что валидация и обработка ошибок не нужны?

И еще много-много вопросов можно задать, но особо смысла не имеет, а весь потенциал JSON-RPC, который используется у спайсвЭба это по сути аналог чистого Celery + AMQP (хотя я бы посоветовал попробовать Redis) с небольшими дополнениями

Вот кстати действительно хорошее и наглядное сравнение этих двух архитектур и почему использовать RPC не для внутренних (и то не для всех) служб приведет к провалу:

https://habr.com/ru/articles/476576/

Руководитель 3D, не поленитесь на досуге почитать. Странно вообще, что у провайдеров со стажем 20+ лет появляются подобные вопросы, когда они прямо специализируются на отказоустойчивости :/

Спасибо за ссылку, это интересная статья, но всё же в ней приведено неполное и довольно однобокое сравнение технологий.

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

Зарегистрируйтесь на Хабре, чтобы оставить комментарий