RESTful Web Services: Предупреждение Race Conditions

Одна из основных предпосылок веб-служб RESTful заключается в том, что HTTP следует рассматривать как протокол приложения, а не только как транспортный протокол. Он включает в себя целый набор семантики, который позволяет нам создавать надежные распределенные системы. А в некоторых случаях, когда несколько потребителей манипулируют одним и тем же ресурсом, изменяя его состояние, решение должно быть достаточно надежным, чтобы предотвратить попадание системы в состояние гонки (race condition).

Как HTTP может предотвратить это?

HTTP обеспечивает простой , но в тоже время сильный механизм выравнивания состояния ресурсов путем использования ETag и условных заголовков запроса . ETag – это все, что однозначно идентифицирует объект, например идентификатор, связанный с постоянным ресурсом, контрольную сумму заголовков и тела объекта и т. д. Если этот ресурс изменяется, то есть когда один или несколько его заголовков или объект body, изменяется – тег объекта изменяется соответствующим образом, отражая это новое состояние ресурса.

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

Условные запросы происходят, когда текущий ETag передается в заголовок условного запроса, например If-Match или If-None-Match, когда пользователь запрашивает обновление ресурса. Затем служба проверит предварительное условие, сравнив текущий ETag ресурса с тем, который указан в запросе. Если он удовлетворен, сервер переходит к обработке запроса, в противном случае он приходит к выводу, что ресурс изменился, и отвечает, отправляя 412 Precondition Failed.

Пример

Представлен интернет-магазин товаров для дома, где два сотрудника – Admin1 и Admin2 – отвечают за управление содержимым. В этом сценарии оба администратора пытаются изменить состояние одного и того же продукта (Weber BBQ) примерно в одно и то же время. Admin1 хочет снизить цену продукта до 300 долларов, а Admin2 хочет изменить свое состояние на «Недоступно». Сначала оба администратора получают текущее состояние продукта независимо друг от друга, выполнив следующий GET запрос:

GET /product/1 HTTP/1.1
Host: myshop.com

Обратите внимание, что ответ сервиса содержит заголовок ETag.

HTTP/1.1 200 OK
Content-Length: 265
Content-Type: application/json
ETag: “686897696a7c876b7e”
{
 “name”: “WeberFamilyBBQ”,
 “description”: “Great for parties and cooks a neat roast too.”,
 “price”: 399,
 “status”: “InStock”
}

Затем Admin1 выполняет запрос PUT, включая If-Match заголовок со значением ETag из предыдущего GET.

PUT /product/1 HTTP/1.1
Host: myshop.com
If-Match: “686897696a7c876b7e”
{
 “name”: “WeberFamilyBBQ”,
 “description”: “Great for parties and cooks a neat roast too.”,
 “price”: 399,
 “status”: “InStock”
}

И поскольку состояние продукта не изменилось с момента последнего запроса, значит, запрос успешен! Обратите внимание, что ответ возвращает обновленное значение ETag, отражающее новое состояние продукта.

HTTP/1.1 204 No Content
ETag: “616898r96a8cy86b8eee11”

Через некоторое время после того, как Admin1 обновил продукт, Admin2 выполняет еще один PUTзапрос к тому же продукту, включая тот же If-Match заголовок со значением ETag из GET запроса.

PUT /product/1 HTTP/1.1
Host: myshop.com
If-Match: “686897696a7c876b7e”
{
 “name”: “WeberFamilyBBQ”,
 “description”: “Great for parties and cooks a neat roast too.”,
 “price”: 399,
 “status”: “InStock”
}

Затем служба определяет, что кто-то пытается изменить тот же продукт, используя устаревшее представление ресурсов (ETags разные!), И отвечает 412 Precondition Failed. Никаких race condition!

HTTP/1.1 412 Precondition Failed

Заключение

Хотя ETags и условные заголовки запросов составляют мощный механизм для работы с параллелизмом, следует помнить о том, что в зависимости от объема вычислений, выполняемых сервером для генерации ETag, время отклика может значительно увеличиться. Так что используйте его, только если он вам нужен!

Автор Александр Мартинс

Рейтинг
( Пока оценок нет )
Maxyc Webber/ автор статьи
Мне 35 лет. Опыт профессиональной разработки 15 лет. Занимаюсь разработкой и поддержкой корпоративных систем автоматизации бизнеса, а также высоконагруженными проектами. Мне нравится решать нестандартные проблемы бизнеса. Имею опыт формирования команд под проект, налаживания процесса разработки, коммуникации программистов и заказчиков. Есть опыт работы с зарубежными заказчиками (ОАЭ, Польша, Германия, Швейцария).
Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!:

Этот сайт использует Akismet для борьбы со спамом. Узнайте, как обрабатываются ваши данные комментариев.