Завершение работы виртуальной машины через интерфейс REST
На самом деле это довольно известный пример, выдвинутый Тимом Бреем в 2009 году .
Рой Филдинг, обсуждая проблему, поделился этим наблюдением :
Я лично предпочитаю системы, которые рассматривают отслеживаемое состояние (например, состояние питания) как не редактируемые.
Вкратце, у вас есть один информационный ресурс, который возвращает текущее представление отслеживаемого состояния; это представление может включать гипермедиа ссылку на форму, которая запрашивает изменение в этом состоянии, а форма имеет другую ссылку на ресурс для обработки (каждого) запроса на изменение.
Сет Лэдд имел ключевое понимание проблемы
Мы превратили «Бег» из простого состояния человека в настоящее Существительное, которое можно создавать, обновлять и обсуждать.
Вернем это к перезагрузке машины. Я бы сказал, что вы должны выполнить POST для / vdc / 434 / cluster / 4894 / server / 4343 / перезагрузок. После публикации у вас есть URI, представляющий эту перезагрузку, и вы можете ПОЛУЧИТЬ его для обновления статуса. С помощью магии гиперссылок представление перезагрузки связано с перезагруженным сервером.
Я думаю, что чеканка пространства URI - это дешево, а URI - даже дешевле. Создайте коллекцию действий, смоделированных как Существительные, и POST, PUT и DELETE!
RESTful-программирование - это бюрократия Вогона в веб-масштабе. Как вы делаете что-нибудь RESTful? Придумайте новые документы для этого и оцифруйте документы.
На более изящном языке вы определяете протокол приложения домена для «выключения виртуальной машины» и определяете ресурсы, необходимые для предоставления / реализации этого протокола.
Глядя на свои примеры
PATCH /api/virtualmachines/42
Content-Type:application/json
{ "state": "shutting down" }
Ничего страшного; вы на самом деле не рассматриваете сам запрос как отдельный отдельный информационный ресурс, но вы все равно можете управлять им.
Вы немного пропустили свое представление об изменениях.
Однако с помощью PATCH вложенный объект содержит набор инструкций, описывающих, как ресурс, находящийся в данный момент на исходном сервере, должен быть модифицирован для создания новой версии.
Например, инструкции JSON Patch форматируют инструкции, как если бы вы непосредственно изменяли документ JSON
[
{ "op": "replace", "path": "state", "value": "shutting down" }
]
В вашей альтернативе идея близка, но не совсем верна. PUT
является полной заменой состояния ресурса по целевому URL , поэтому вы, вероятно, не выберете орфографию, которая выглядит как коллекция, как цель представления одного объекта.
POST /api/virtualmachines/42/actions
Соответствует выдумке, что мы добавляем действие в очередь
PUT /api/virtualmachines/42/latestAction
Это согласуется с выдумкой о том, что мы делаем обновление для хвостового элемента в очереди; это немного странно делать это таким образом. Принцип наименьшего удивления рекомендует присваивать каждому PUT свой уникальный идентификатор, а не размещать их все в одном месте и модифицировать несколько ресурсов одновременно.
Обратите внимание, что, поскольку мы обсуждаем написание URI - REST не волнует; /cc719e3a-c772-48ee-b0e6-09b4e7abbf8b
является совершенно громоздким URI для REST. Читаемость, как и с именами переменных, является отдельной проблемой. Использование написания, соответствующего RFC 3986 , сделает людей намного счастливее.
CQRS
Что если у нас есть домен CQRS со многими такими «действиями» (или командами), которые потенциально могут привести к обновлениям нескольких агрегатов или не могут быть сопоставлены с операциями CRUD на конкретных ресурсах и подресурсах?
Грег Янг о CQRS
CQRS - это очень простой шаблон, который предоставляет множество возможностей для архитектуры, которая в противном случае может не существовать. CQRS не является последовательной последовательностью, это не события, это не обмен сообщениями, у него нет отдельных моделей для чтения и записи, и при этом он не использует источник событий.
Когда большинство людей говорят о CQRS, они на самом деле говорят о применении шаблона CQRS к объекту, который представляет сервисную границу приложения.
Учитывая, что вы говорите о CQRS в контексте HTTP / REST, кажется разумным предположить, что вы работаете в этом последнем контексте, так что давайте продолжим.
Этот, на удивление, даже проще, чем ваш предыдущий пример. Причина этого проста: команды - это сообщения .
Джим Уэббер описывает HTTP как протокол приложений офиса 1950-х годов; работа выполняется путем приема сообщений и помещения их в почтовые ящики. Та же идея верна - мы получаем чистую копию формы, заполняем ее известной нам спецификой, доставляем ее. Та да
Должны ли мы пытаться моделировать столько команд, сколько конкретных создает или обновляет конкретные ресурсы, где это возможно (следуя первому подходу из примера I), и использовать «конечные точки действия» для остальных?
Да, поскольку «конкретные ресурсы» - это сообщения, а не сущности в доменной модели.
Основная идея: ваш REST API все еще является интерфейсом ; Вы должны быть в состоянии изменить базовую модель без необходимости изменения сообщений клиентами. Когда вы выпускаете новую модель, вы выпускаете новую версию веб-конечных точек, которые знают, как использовать протокол вашего домена и применять его к новой модели.
Модель CQRS лучше подходит для API, подобного RPC?
Не совсем - в частности, веб-кеши являются отличным примером «в конечном итоге согласованной модели чтения». Делая каждое из ваших представлений независимо адресуемыми, каждое со своими правилами кэширования, вы получаете бесплатное масштабирование. Относительно малообращенный подход к чтению RPC относительно невелик.
Для записи это сложный вопрос: отправка всех команд одному обработчику в одной конечной точке или в одном семействе конечных точек, безусловно, проще . REST на самом деле больше о том, как вы общаетесь, где конечная точка находится для клиента.
Преимущество обработки сообщения как его собственного уникального ресурса заключается в том, что вы можете использовать PUT, предупреждая промежуточные компоненты о том, что обработка сообщения идемпотентна, так что они могут участвовать в определенных случаях обработки ошибок. , (Обратите внимание: с точки зрения клиентов, если ресурсы имеют разные URI, то они являются разными ресурсами; тот факт, что все они могут иметь одинаковый код обработчика запросов на исходном сервере, является подробностью реализации, скрытой униформой интерфейс).
Филдинг (2008)
Я должен также отметить, что вышеупомянутое еще не полностью RESTful, по крайней мере, как я использую термин. Все, что я сделал, это описал сервисные интерфейсы, которые не более чем любой RPC. Чтобы сделать его RESTful, мне нужно добавить гипертекст, чтобы представить и определить сервис, описать, как выполнить отображение с использованием форм и / или шаблонов ссылок, и предоставить код для объединения визуализаций полезными способами.