Веб-сервисы RESTful

Окончание статьи. Читать с начала.

Не хранит состояния

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

Не хранящий состояния проект выглядит так:

Запрос1: GET http://MyService/Persons/1 HTTP/1.1
Запрос2: GET http://MyService/Persons/2 HTTP/1.1

Каждый из этих запросов можно рассматривать отдельно.

С другой стороны, хранящий состояние проект выглядит так:

Запрос1: GET http://MyService/Persons/1 HTTP/1.1
Запрос2: GET http://MyService/NextPerson HTTP/1.1

Чтобы обработать второй запрос, сервер должен помнить последний PersonID, который извлек клиент. Другими словами, серверу необходимо помнить текущее состояние — в противном случае Запрос2 не может быть обработан. Разрабатывайте свой сервис таким образом, чтобы запрос никогда не ссылался на предыдущий. Не хранящие состояние сервисы легче хостить, легко поддерживать, и они являются более масштабируемыми. Кроме того, такие сервисы дают лучший отклик по времени на запросы, т.к. для них легче балансировать нагрузку.

Связи между ресурсами

Представление ресурса может содержать ссылки на другие ресурсы подобно тому, как HTML-страница ссылается на другие страницы. Представления, возвращаемые сервисом, должны направлять поток процесса как и в случае вебсайта. Когда вы посещаете вебсайт, вам показывают индексную страницу. Вы щелкаете одну из ссылок и переходите на другую страницу, и т.д. Здесь представлением является HTML-документ, и пользователя перемещают по сайту сами HTML-документы. Пользователю не нужно иметь карту, чтобы перемещаться по сайту. Сервис может (и должен) проектироваться в подобной манере.

Давайте рассмотрим случай, когда клиент запрашивает один ресурс, который содержит много других ресурсов. Вместо формирования дампа всех этих ресурсов вы можете перечислить ресурсы и дать ссылки на них. Ссылки позволяют представлениям иметь небольшой размер.

Например, если множество Persons может быть частью Club, тогда Club может быть представлен в MyService, как показано в листинге 6:

Листинг 6. Клуб (Club) со ссылками на участников (Persons).

1	<Club>        
2		<Name>Authors Club</Name>
3		<Persons>
4			<Person>
5				<Name>M. Vaqqas</Name>
6				<URI>http://MyService/Persons/1</URI>
7			</Person>
8			<Person>
9				<Name>S. Allamaraju</Name>
10				<URI>http://MyService/Persons/12</URI>
11			</Person>
12		</Persons>
13	</Club>   

Кэширование

Кэширование – это концепция сохранения сгенерированных результатов, и использования сохраненных результатов вместо их повторной генерации, если тот же запрос поступает в ближайшем будущем. Это может быть сделано на клиенте, на сервере, или на любом другом компоненте между ними, например, на прокси-сервере. Кэширование – это прекрасный способ увеличить производительность сервиса, однако, если не управлять им правильно, клиент может получать устаревшие результаты.

Кэширование управляется следующими HTTP заголовками:

ЗаголовокПриложение
DateДата и время, когда было сгенерировано представление.
Last ModifiedДата и время, когда сервер последний раз модифицировал это представление.
Cache-ControlЗаголовок HTTP 1.1, используемый для управления кэшированием.
ExpiresДата и время, когда истекает срок представления. Для поддержки клиентов HTTP 1.0.
AgeВремя в секундах, прошедшее с момента выборки с сервера. Может быть вставлено промежуточной компонентой.

Значения этих заголовков могут использоваться в комбинации с директивами в заголовке Cache-Control для проверки валидности кэшированных результатов. Наиболее общими директивами для заголовка Cache-Control являются:

ДирективаПриложение
PublicПо умолчанию. Означает, что любой компонент может кэшировать это представление.
PrivateПромежуточные компоненты не могут кэшировать это представление, а только клиент или сервер.
no-cache/no-storeКэширование выключено.
max-ageДлительность интервала в секундах после даты-времени, отмеченного в заголовке Date, в течение которого это представление является валидным.
s-maxageПодобно max-age только имеет значение для кэширования на посреднике.
must-revalidateУказывает, что представление должно повторно проверяться сервером, если max-age истекло.
proxy-validateПодобно max-validate только имеет значение для кэширования на посреднике.

Вы видели некоторые из этих заголовков и директив в листинге 5. В зависимости от природы ресурса сервис может назначить значения этих заголовков и директив. Например, сервис, представляющий изменения на фондовой бирже, может установить ограничение на возраст кэша (cache age), установив его минимально возможным, или даже полностью выключив кэширование, т.к. эта информация является критичной, и пользователи должны получать все время самые свежие результаты. С другой стороны, публичная картинная галерея, чей фонд меняется не столь быстро, может установить длительный возраст кэша. Сервер, клиент и любой посредник между ними должны следовать этим директивам и избегать хранения устаревших данных.

Документирование RESTful сервиса

RESTful-сервисам не обязательно требуется документ, чтобы помочь клиентам разобраться с ними. Благодаря URI, ссылкам и однородному интерфейсу, весьма просто обнаружить RESTful-сервисы во время выполнения. Клиент может просто узнать базовый адрес сервиса, и, исходя из него, обнаружить сервис, выполняя навигацию по ресурсам с помощью ссылок. Метод OPTION может использоваться эффективно в процессе обнаружения сервиса.

Это не означает, что сервисы RESTful вообще не требуют документации. Нет оправданий отсутствию документации к вашему сервису. Вы должны документировать каждый ресурс и URI для разработчиков клиентских приложений. Вы можете использовать любой формат для структурирования вашего документа, однако он должен содержать достаточно информации о ресурсах, URI, доступных методах и любой другой информации, требуемой для доступа к вашему сервису. В нижеприведенной таблице содержится образец документации на MyService. Это простой и короткий документ, содержащий все аспекты MyService , достаточные для разработки клиента.

Имя сервиса: MyService
Адрес: http://MyService/
РесурсМетодыURIОписание
PersonGET, POST, PUT, DELETEhttp://MyService/Persons/{PersonID}Содержит информацию о лице. {PersonID} не обязательно. Формат: text/xml
ClubGET, POST, PUThttp://MyService/Clubs/{ClubID}Содержит информацию о клубе. Клуб может объединять многих людей. {ClubID} не обязательно. Формат: text/xml
SearchGEThttp://MyService/Search?Найти лицо или клуб. Формат: text/xml. Параметры запроса:
Name: строка; имя лица или название клуба.
Country: строка; необязательный, название страны лица или клуба
Type: строка, необязательный; Person или Club. При отсутствии поиск ведется и среди лиц, и среди клубов

Вы можете также задокументировать представления каждого ресурса и привести примеры представлений.

Заключение

REST – прекрасный способ разработки легких веб-сервисов, которые просто разрабатывать, поддерживать и обнаруживать. HTTP предоставляет прекрасный интерфейс для создания RESTful-сервисов, обладающих однотипным интерфейсом и возможностью кэширования. Однако разработчикам следует правильно использовать эти возможности. Если мы усвоим основы, RESTful-сервис может легко разрабатываться, используя любую из существующих технологий, например: Python, .NET или Java.

страницы 1 2 3

Перевод Моисеенко С.И. © 31.12.2016