Чи REST обмежується лише оптимістичним контролем одночасності?


9

Контекст

Через безхарактерність архітектурного стилю REST, який передбачає, що кожен запит стоїть повністю самостійно, ведучий сервер ніколи не зберігає інформацію про клієнта.

Таким чином, песимістичний контроль одночасності не підходить, оскільки він вимагає того серверного магазину, який клієнт отримує блокування на ресурсі. Потім використовується оптимістичний контроль за одночасністю за допомогою Etagзаголовка. (btw, як я запитав там /programming/30080634/concurrency-in-a-rest-api )

Проблема

Основна проблема оптимістичного механізму контролю за сумісністю полягає в тому, що ви дозволяєте весь час, всім клієнтам, виконувати будь-які операції.

І я хотів би цього уникнути, не порушуючи принципу без громадянства REST. Я маю на увазі, що всі клієнти не можуть виконати жодної операції в будь-який час.

Питання

На мій погляд, це було б можливо з полуоптімістіческом механізм управління паралелізмом, як цей:

  • Клієнти можуть запитати маркер
  • Можна створити лише один маркер і має обмежений термін дії
  • Для виконання операцій над ресурсами (такими як POST або PUT ) клієнт повинен надати цей маркер як частину тіла (або заголовка?) Запиту. Клієнт, який не має маркера, не може робити ці операції.

Це дуже схоже з оптимістичним контролем одночасності, за винятком того, що лише один клієнт може робити деякі операції (той, що отримав маркер) ... навпаки "всі клієнти можуть робити всі операції".

Чи сумісний цей механізм із архітектурним стилем REST? Чи порушує це якесь обмеження? Я думав задати питання SO, але це здається питанням на високому рівні, пов'язаним з дизайном програмного забезпечення.


1
Насправді це досить просто: вам потрібно Transactionчітко моделювати як Ресурс.
Йорг W Міттаг

Що це змінюється? Не обов’язково розумію ваш коментар. Я не займаюся контролем одночасності транзакцій, а скоріше, щоб сказати клієнтові «добре зараз, ви абсолютно впевнені, що ніхто не змінить ресурс» (так як він отримав унікальний маркер).
AilurusFulgens

1
Яка різниця? З одного боку, ви використовуєте Etag, щоб перевірити, кому дозволено оновлювати "поточну" версію; якщо це зіткнеться, ви повинні оновити свою версію і виконати оновлення після цього. З іншого боку, у вас є ваш механізм "фіксації": одне дозволено, іншим доведеться чекати. Звучить приблизно однаково. Мінус другого підходу: 2 запити - 1 для блокування та 1 для оновлення. В оптимальному випадку у вас є лише одне оновлення за допомогою підходу Etag.
Томас Джунк

Ну, взагалі кажучи про контроль за сумісністю ... друге, що "програв гонку", завжди доведеться чекати (просто з різних причин, я згоден з цим). Відмінність від Etag? Якщо Etagви ніколи не впевнені, що ваші операції будуть завершені, у вас може виникнути ситуація, коли ви ніколи не виконаєте жодних операцій. З блокуванням ви впевнені, що принаймні виконаєте свою операцію. Тож наявність простого блокування - це лише середина між середовищем, де можуть статися "високі конфлікти" та "рідкісні конфлікти".
AilurusFulgens

Відповіді:


3

Ніколи не слід (як ніколи НЕБЕ) блокувати будь-який ресурс під час очікування взаємодії з користувачем.

У якийсь момент деякі ваші користувачі вилетять на довгі вихідні, залишивши деякі життєві записи заблокованими.

Ах, але ви не дозволите цього статися, тому що у вас є якась розумна схема розв'язання часу / тупику; то в якийсь момент це піде жахливо неправильно, і користувач, який отримав приємне повідомлення "Ваш віджет замовлено", буде кричати на довідковій службі, вимагаючи дізнатися, чому його віджет не доставлений.

Більшість людей можуть мати справу з повідомленням "вибачте, інший користувач щойно замовив цю частину".


Ти це добре пояснив. Хоча я не повністю переконаний у вашому першому реченні: у якийсь момент ви б гарантували, що ніхто інший, як ви, не зможе виконати замовлення. Але добре, ваше останнє речення - це гарне підсумок, у 99% випадків це так.
AilurusFulgens

1
Якщо вам потрібно заблокувати запис для конкретного користувача, то зробіть це на рівні програми. Або буде простий атрибут "LockedBy", або з більш складним механізмом версії та робочого процесу.
Джеймс Андерсон

Що ви маєте на увазі під "додатком"? Якщо ви додасте на ресурс атрибут "LockedBy", ви зберігаєте інформацію про клієнта на своєму сервері. А може я не зрозумів ваш коментар. Якщо ви можете надати деякі деталі, було б чудово!
AilurusFulgens

1
@AilurusFulgens - Ви додаєте атрибут LockedBy (і, можливо, мітку часу LockedOn) до вашої бази даних. У коді програми ви встановлюєте ім'я користувача та час кожного разу, коли клієнт починає взаємодію з оновленням. Ви вимикаєте його, коли клієнт закінчується - тоді вам потрібно розробити деякі ділові правила для вирішення конфліктів та таймаутів тощо.
Джеймс Андерсон,

2

Використання жетонів дуже поширене в API, ці маркери зазвичай надсилаються як заголовки і мають чіткий життєвий цикл. Подумайте, наприклад, OAuth.

Незалежно від мови та програми програмування, API REST схожі.

Я можу придумати кілька сценаріїв, де потрібно обмежити одночасність, два з них:

  1. Кілька клієнтів, що оновлюють ті самі ресурси, що й рядок бази даних. Наприклад: два паралельних запити, один видаляє запис, а другий намагається оновити той самий запис. Залежно від вашої бази даних і того, як ви її налаштували, ви можете отримати блокування записів або недійсну операцію, оскільки дані будуть іншими або не існуватимуть.

  2. Супер користувач або адміністратор, який виконує спеціальні дії з API.


Що робити у цих випадках?

  1. Використовуйте транзакції в базі даних, одиночні кнопки, блокування та подібні механізми для синхронізації доступу до ресурсів.

  2. Маркер може працювати, я думаю, що буде краще, якщо ви не зберігатимете інформацію про клієнта, а лише про сам маркер. На одному кроці ви можете перевірити користувача та призначити маркер. Тоді просто підтвердіть, що маркер живий і дійсний. Використовуйте маркер, який можна розшифрувати, щоб отримати додаткову інформацію. Ви можете зберігати, якщо це спеціальний маркер, і вмикати його можна за раз. Таким чином ви перевіряєте маркер, а не користувача.

Я сподіваюся, що це допомагає.


Так, я очікував відповіді про схожість токена та механізму OAuth. Хоча останній присвячений аутентифікації. Я не зрозумів вашого сценарію 1. Найскладнішою частиною, що стосується паралельності в API REST, є збереження обмеження без громадянства ... це означає, що сервер не зберігає інформацію про клієнта. Ваш сценарій 2 - саме те, що я зараз роблю! :)
AilurusFulgens

Я відповів на ваше запитання?
Пабло Гранадос

Ні вибач. Я схвально відгукнувся на вашу відповідь, оскільки вона дає хороший огляд проблеми, але, на жаль, imo, вона насправді не вирішує її.
AilurusFulgens

0

ВІДПОВІДЬ тільки одна занадто примітивна, насправді. Ви можете розпочати роботу з REST, але, зрештою, вашій багатій програмі знадобляться запити з приєднаннями та оновлення транзакцій. Кожен розробник, який намагається додати ці речі самостійно, був би схильним до помилок та суперечливим. На щастя, існує новий стандарт під назвою OData, який робить саме це. Він шарує поверх REST і надає (1) мову запитів, що дозволяє просте приєднання з використанням навігаційних властивостей (без необхідності виставляти сторонні ключі), і (2) пакетної обробки, що включає набори атомних змін.

Дивіться тут (1) https://stackoverflow.com/a/3921423/471129 та,

Дивіться тут і для (2) https://stackoverflow.com/a/21939972/471129

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.