2016-06-29 3 views
0

Я разрабатываю веб-службу для регулярного получения обновлений списков. На данный момент список все еще может быть смоделирован как единый объект (/lists/myList) или фактическая коллекция со многими ресурсами (/lists/myList/entries/<ID>). Списки большие (миллионы записей), а обновления небольшие (часто менее 10 изменений).HTTP ReST: обновление больших коллекций: лучший подход, чем JSON PATCH?

Клиент получает URL-адреса службы веб и списки для распространения, например:

Затем он будет настраивать списки и обновления. Вероятно, но не определено, есть ли какая-либо база данных за URL-адресами веб-службы.

Я занимаюсь исследованием, и, кажется, HTTP PATCH с использованием формата патча JSON - лучший подход.

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

PUT /lists/requiredItems 
Content-Type: application/json 


{ 
    "priority": 1, 
    "entries": { 
    "1": { 
     "color": "red", 
     "validUntil": "2016-06-29T08:45:00Z" 
    }, 
    "2": { 
     "country": "US" 
    } 
    } 
} 

Для обновлений, клиент в первую очередь необходимо знать, что список выглядит сейчас на сервере. Для этого я бы добавил свойство «ревизия» в объект списка.

Тогда, я бы запросить этот атрибут:

GET /lists/requiredItems?property=revision 

Тогда клиент будет видеть, что необходимо изменить между пересмотром на сервере и последнюю версию известного клиента и составить JSON патч. Пример:

PATCH /list/requiredItems 
Content-Type: application/json-patch+json 

[ 
    { "op": "test", "path": "revision", "value": 3 }, 
    { "op": "add", "path": "entries/3", "value": { "color": "blue" } }, 
    { "op": "remove", "path": "entries/1" }, 
    { "op": "remove", "path": "entries/2/country" }, 
    { "op": "add", "path": "entries/2/color", "value": "green" }, 
    { "op": "replace", "path": "revision", "value": 10 } 
] 

Вопросы:

  • Этот подход имеет недостаток, заключающийся в несколько меньшей поддержки клиентов в связи с не-часто используется HTTP-глагола пластыря. Существует ли более совместимый подход, не жертвуя поддержкой HTTP (idempotency et cetera)?
  • Моделирование отдельных записей списка в виде отдельных ресурсов и использования PUT и DELETE (возможно, с ETag и/или If-Match) представляется вариант (PUT /lists/requiredItems/entries/3, DELETE /lists/requiredItems/entries/1PUT /lists/requiredItems/revision), но как бы я убедиться, что все эти операции применяются, когда сетевые капли в середине цепочки обновлений? Может ли HTTP PATCH работать с несколькими ресурсами?
  • Есть ли лучший способ «версии» списков, возможно, неявно также улучшить их обновление? Обратите внимание, что клиент определяет номер версии.
  • Правильно ли запрашивать номер версии с GET /lists/requiredItems?property=revision? Должен ли он быть отдельным ресурсом, например /lists/requiredItems/revision? Если это должен быть отдельный ресурс, как бы я его физически обновить (т. Е. Список и ревизия обновлены или оба не обновляются)?
  • Будет ли он работать в патче JSON, чтобы сначала проверить значение версии 3, а затем обновить его до 10 в том же патче?
+0

Пожалуйста, не спрашивайте более одного вопроса за раз. Все они действительны, но вы, вероятно, не получите ответа на все из них. –

+0

@ LutzHorn: спасибо. Ты прав. Должен ли я удалить все, кроме одного вопроса, и переставить остальные отдельно? Вводная часть будет такой же ... –

ответ

2

Этот подход имеет тот недостаток, что немного меньше поддержки клиентов в связи с не-часто используется HTTP глагола PATCH.

Насколько я могу судить, PATCH действительно только в том случае, Ваш сервер действует как немой документ магазин, где действие буквально «необходимо обновить вашу копию документа в соответствии со следующим описанием».

Итак, если ваш ресурс действительно является документом JSON, который описывает список с миллионами записей, тогда JSON-Patch - отличный ответ.

Но если вы ожидаете, что патч, как побочный эффект, обновит объект в вашем домене, тогда я подозрюю.

Является ли HTTP PATCH разрешенным для работы с несколькими ресурсами?

RFC 5789

Метод PATCH влияет на ресурс, определенный в Request-URI, и он также может иметь побочные эффекты на другие ресурсы

Я не заинтересован в запрашивая номер ревизии; у него, похоже, нет явного преимущества перед использованием подхода ETag/If-Match. Некоторые очевидные недостатки - кэши между вами и клиентом не знают, что список и номер версии связаны; кеш с радостью сообщит клиенту, что версия 12 списка - версия 7, или наоборот.

+0

Спасибо! Веб-служба может иметь или не иметь базы данных; Я разрабатываю клиент и веб-сервис, но не сервер. На стороне сервера будет несколько различных сторонних реализаций. Я добавил некоторые разъяснения в начале вопроса. –

+0

Я не понимаю, как HTTP надеется включить кеширование, если PATCH to/service/list1 может влиять на любой другой ресурс. Просто недействительно весь кеш при каждом запросе PATCH? –

+0

Справедливости ради PATCH, те же проблемы возникают с POST, PUT, DELETE. Когерентность кеша является одной из двух трудных проблем. – VoiceOfUnreason

0

Отвечая на мой вопрос. Мое первое поле может быть основано на мнениях, и, как уже указывалось, я задал много вопросов в одном сообщении. Тем не менее, вот резюме того, на что ответили другие (VoiceOfUnreason), и мои собственные дополнительные исследования:

ETags - это хеш-ресурс ресурсов HTTP. Их можно комбинировать с заголовками If-Match, чтобы иметь систему управления версиями. Однако заголовки ETag обычно не используются для объявления ETag ресурса, который создается (PUT) или обновленного (POST/PATCH). Сервер, хранящий ресурс, обычно определяет ETag. Я не нашел ничего явно запрещающего это, но многие реализации могут предполагать, что сервер определяет ETag и путается, когда он снабжен PUT или PATCH.

Отдельный ресурс редакции является действующей альтернативой ETags для управления версиями. Этот ресурс должен быть обновлен одновременно с ресурсом, который является пересмотром.

Не имеет смысла на уровне HTTP, чтобы иметь транзакции фиксации/откат, если только не моделирование самой транзакции как ресурса ReST, что усложнит ситуацию.

Однако некоторые свойства пластыря позволяют использовать его для этого:

  • HTTP-PATCH должен быть атомарным и может работать на нескольких ресурсах.RFC 5789:
    • Сервер должен применить весь набор изменений атомарны и никогда не обеспечивает (например, в ответ на GET во время этой операции) частично модифицированного представления. Если весь файл патча не может быть успешно применен, сервер НЕ ДОЛЖЕН применять какие-либо изменения.
    • Метод PATCH влияет на ресурс, идентифицируемый Request-URI, и также может иметь побочные эффекты для других ресурсов; то есть новые ресурсы могут быть созданы или уже модифицированы приложением PATCH. PATCH не является ни безопасным, ни идемпотентная
  • JSON PATCH может состоять из нескольких операций на нескольких ресурсах и все они должны быть применены или нет, должны быть применены, что делает его неявной транзакции. RFC 6902:
    Операции применяются последовательно в порядке их появления в массиве.

Таким образом, ревизия может быть смоделирована как отдельный ресурс и все еще обновляться в одно и то же время. Запрос текущей версии - это просто GET. Перенос транзакции - это один запрос PATCH, содержащий сначала проверку ревизии, затем операции над ресурсами (ресурсами) и, наконец, операцию обновления ресурса ревизии.

Сервер все еще может опубликовать версию как ETag основного ресурса.

Смежные вопросы