Подход для REST-запроса с длительным временем выполнения?

Мы создаем службу REST, выполнение которой займет около 5 минут. Он будет вызываться только несколько раз в день внутренним приложением. Существует ли проблема с использованием запроса REST (т. Е. HTTP), выполнение которого занимает 5 минут?

Должны ли мы беспокоиться о тайм-аутах? Должны ли мы запускать запрос в отдельном потоке на сервере и проводить опрос клиентов на предмет статуса?

4 ответа

Решение

Предполагая, что вы можете настроить тайм-ауты HTTP, используя любую платформу, которую вы выберете, вы можете запросить через GET и просто зависнуть на 5 минут.

Однако может быть более гибким инициировать выполнение через POST, получить квитанцию ​​(номер / идентификатор и т. Д.), А затем выполнить GET, используя это через 5 минут (и, возможно, повторить попытку, если ваша процедура не займет ровно 5 минут). каждый раз). Если запрос все еще выполняется, верните соответствующий код ошибки HTTP (возможно, 404, но что бы вы вернули для GET с несуществующей квитанцией?) Или верните результаты, если они доступны.

Это один из подходов.

Создайте новый запрос для выполнения ProcessXYZ

POST /ProcessXYZRequests

201-Created
Location: /ProcessXYZRequest/987

Если вы хотите увидеть текущий статус запроса:

GET /ProcessXYZRequest/987

<ProcessXYZRequest Id="987">
  <Status>In progress</Status>
  <Cancel method="DELETE" href="/ProcessXYZRequest/987"/>
</ProcessXYZRequest>

когда запрос закончится, вы увидите что-то вроде

GET /ProcessXYZRequest/987

<ProcessXYZRequest>
  <Status>Completed</Status>
  <Results href="/ProcessXYZRequest/Results"/>
</ProcessXYZRequest>

Используя этот подход, вы можете легко представить, что дадут следующие запросы

GET  /ProcessXYZRequests/Pending
GET  /ProcessXYZRequests/Completed
GET  /ProcessXYZRequests/Failed
GET  /ProcessXYZRequests/Today

Как указывает Брайан Агнью, 5 минут вполне поддаются управлению, если они несколько расточительны, если можно контролировать параметры тайм-аута. В противном случае должны быть выполнены как минимум два запроса: первый, чтобы запустить процесс, производящий результат, и второй (и третий, четвертый и т. Д., Если для компиляции результата требуется больше времени, чем ожидалось), для запроса результата.

Брайан Агнью и Даррел Миллер оба предлагают похожие подходы для двух (+)- пошагового подхода: POST запрос к конечной точке фабрики, запуск задания на сервере, а затем GET результат из конечной точки возвращенного результата.

Хотя вышеприведенное является очень распространенным решением и действительно соответствует букве ограничений REST, оно очень сильно пахнет RPC. То есть вместо того, чтобы сказать "предоставьте мне представление этого ресурса", в нем говорится "запустить это задание" (RPC), а затем "предоставить мне представление ресурса, являющегося результатом выполнения задания" (REST). РЕДАКТИРОВАТЬ: я говорю очень свободно здесь. Чтобы быть ясным, ни одно из этого явно не противоречит ограничениям REST, но это очень похоже на навязывание подхода без RESTful в одежде REST, теряя его преимущества (например, кеширование, идемпотентность) в процессе.

Поэтому я бы предпочел, чтобы, когда клиент впервые попытался получить ресурс, сервер ответил 202 "Принят" ( http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html), возможно, с "попытаться вернуться через 5 минут" где-то в объекте ответа. После этого клиент может опросить ту же конечную точку, чтобы ПОЛУЧИТЬ результат, если он доступен (в противном случае вернуть еще 202 и повторить попытку позже).

Некоторые дополнительные преимущества этого подхода состоят в том, что одноразовые ресурсы (такие как задания) не создаются излишне, две отдельные конечные точки не должны запрашиваться (фабрика и результат), и аналогично вторая конечная точка не должна определяться на основе анализа ответа от во-первых, тем проще. Кроме того, результаты могут быть кэшированы "бесплатно" (по кодам). Установите время истечения срока действия кэша в заголовке результата в соответствии с тем, как долго результаты являются "действительными", в некотором смысле, для вашей проблемной области.

Хотелось бы назвать это учебным примером "ресурсно-ориентированного" подхода, но, возможно, по иронии судьбы, в главе 8 "Веб-сервисы RESTful" предлагается двухконечный, фабричный подход. Пойди разберись.

Если вы контролируете оба конца, тогда вы можете делать все, что захотите. Например, браузеры, как правило, запускают HTTP-запросы с заголовками "закрытие соединения", поэтому у вас остается меньше вариантов;-)

Имейте в виду, что если у вас есть некоторые межсетевые экраны NAT/Firewall, у вас могут быть некоторые разрываемые соединения, если они неактивны в течение некоторого времени.

Могу ли я предложить зарегистрировать процедуру "обратного вызова"? Клиент отправляет запрос с "конечной точкой обратного вызова" на сервер, получает "билет". Как только сервер завершает работу, он выполняет "обратный вызов" клиента... или клиент может проверить состояние запроса через идентификатор билета.

Другие вопросы по тегам