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

REST/CRUD. Я неправильно его готовлю? Часть 2

Время на прочтение 3 мин
Количество просмотров 6K

Вступление


В первой части я начал делиться своими наблюдениями по поводу реализации HTTP/GET в REST. В этой — попробуем рассмотреть вопросы версионирования и архитектуры. Приступим?

Версионирование — то, без чего Ваш API бесполезен


Помните прошлую публикацию?
URL/URN/URI/resource/slug — все эти понятия мы рассмотрели. Чего же боле?
Вся адресация из первой статьи — синтетическая, никакого отношения к реальному проекту она не имеет.
ТАК ПИСАТЬ API НЕЛЬЗЯ!
Нельзя потому что в URI напрочь отсутствует такая важная вещь как версионирование.
Почему URI? Почему не URL? Почему не URN? Да потому что наш API предоставляет доступ к состояниям объектов внутри коллекций. Т.е. нам не принципиально какой URL (читай «на каком сервере») или какой URN (читай «какой бекенд») будут у объекта, нам важно знать оъект какой версии мы используем.
В разных источниках мелькает тема версионирования API, но сфрмулирована, на мой взгляд, она не очень удачно. Считается, что, версионирование позволит не смешивать разные реализации API (т.е. версии ассоциируют с URL/URN).
А сейчас откровение: А кто запретил демону (URN), запущенному на сервере (URL), обслуживающему коллекцию (resource), версии v2 принимать объекты версии v1? От того что объект имеет версию v1 он перестал быть валидным? Объект пользователя перестал быть пользователем? Непонятно? Ок. Давайте по порядку.

Архитектура


Из материалов википедии в разделе «архитектура REST» есть следующие строки:
Клиент может взаимодействовать не напрямую с сервером, а с произвольным количеством промежуточных узлов. При этом клиент может не знать о существовании промежуточных узлов, за исключением случаев передачи конфиденциальной информации.

там же есть перечень целей которые пытаемся достич
  • масштабируемость
  • портативность компонентов
  • легкость внесения изменений
  • способность эволюционировать


Чего хотел добиться автор? Нет, «мир во всем мире» — это понятно, но все же…

Попробуем декомпозировать задачу и воспользуемся «типичными» решениями горизонтального масштабирования:
  1. Множество серверов обслуживающих клиентские запросы реализуем через DNS
  2. В каждом сервере имеем балансировку по множествам бекендов на разных внутренних серверах
  3. В каждом бекенде от 1 до n коллекций


А теперь вопрос на миллион: как коллекции общаются друг с другом? Логичен вопрос «ЗАЧЕМ?», но готов ответить «синтетическим» примером:
Дано:
  • Сервер #1 с бекендом, в котором есть коллекция users
  • Сервер #2 с бекендом, в котором есть коллекция groups

Задача: При добавлении пользователя в коллекцию groups — проверять что пользователь присутствует в коллекции users. При получении пользователей из groups определять все еще существует этот пользователь в коллекции users, и, если нет — удалять его из коллекции groups и не передавать пользователю информацию о нем.

Оставим сейчас тонкости URL/URN/URI/etc и того что по ним передается. Вопрос в том, как в распределенной системе добиться консистентного состояния? Первое что приходит в голову — использовать тот же REST до соседней коллекции, но где взять отказоустойчивый сервер с кешированием и балансировкой нагрузки?! СТОП! Так все уже есть! Бери и используй!

Хм… ок, есть у нас масштабируемый http-кластер (да, я знаю что это не кластер в строгом смысле этого слова), а причем тут версионирование? А притом, что, не рационально в распределенной системе, которая поддерживает коммуникации между участниками, городить огород со стеком старого API (читай «делать еще один кластер по меньше»). И, в ряде случаев, таскать бекенды между версиями. Например в версии 2 изменилась только коллекция user и добавилась contacts. Как groups переедет в версию 2?

Критикам


Предрекая вопросы попытаюсь внести ясность по некоторым пунктам.

О чем вобще речь? Что за бред?
Речь о том, что, версионирование — свойство коллекции а не API. В противном случае — никакого масштабирования.

У Вас проблема в архитектуре. Должно быть как то так: /groups/group_name/users/user_name
Да, так оно и есть, но:
… до тех пор пока пользователь может находться в одной группе, в противном случае у вас по 2-ум и более URI будет возвращаться один и тот же объект.
… до тех пор пока у пользователя обязана быть группа, в противном случае придется вводить фейковые группы (default, global, system, all — правда информативненько?)

REST для коммуникаций в распределенной системе? Вы в своем уме?!
Не беспокойтесь, я знаю что «белые люди» для этого используют асинхронные кластеризуемые message-брокеры поверх транспортных каналов с гарантированной полосой и прочих прелестей корпоративных систем. Это «синтетический» пример, да и не такой уж и плохой в рамках 3-5 серверов.

Это все что у Вас есть по версионированию?
О, нет! Я только начал!

P.S. Друзья, на часах 3:00, а значит пора спать. Прошу всех высказываться в коментариях. Без Ваших фидбеков писать ооочень тяжело.
Теги:
Хабы:
-4
Комментарии 2
Комментарии Комментарии 2

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн