В статье представлен набор инструментов, необходимых для создания REST API. Инструменты не зависят от платформы, то есть они применимы к API REST, созданным с использованием любого технологического стека. Цель статьи - познакомить начинающих разработчиков API с различными этапами разработки API и представить инструменты, которые помогают на этих этапах. Подробное освещение этих инструментов можно найти в Интернете. Этапы разработки API перечислены ниже.
- Проектирование. Основной целью здесь является определение формы API, интерфейсов документов и предоставление конечных точек.
- Тестирование. На этом этапе проводится функциональное тестирование API, путем отправки запроса и анализа ответа на разных уровнях видимости, а именно: приложение, HTTP, сеть.
- Веб-хостинг. При развертывании в Интернете существуют инструменты HTTP, которые помогают с размещением API-интерфейсов для повышения производительности, безопасности и надежности.
- Производительность. Прежде чем перейти к работе, мы используем инструменты для тестирования производительности API-интерфейсов, информирующие нас о нагрузке,: которую могут поддерживать API-интерфейсы.
- Возможность наблюдения. После развертывания API в рабочей среде тестирование в производственной среде обеспечивает общее состояние работоспособных API и предупреждает нас о любых проблемах.
- Управление. В заключение, мы рассмотрим некоторые инструменты для управления API, такие как формирование трафика, развертывание и т.д.
На следующем рисунке показаны различные этапы и используемые инструменты.
Проиллюстрируем использование инструментов для API, предоставляемых веб-приложением, при разработке каждого этапа API. Product Catalog
- это веб-приложение Spring Boot, которое управляет каталогом товаров. Он предоставляет API REST для выполнения операций CRUD над каталогом продуктов. Код доступен
здесь
.
Проектирование
На этапе проектирования разработчик API взаимодействует с клиентами API и поставщиком данных для получения формы API. REST API по сути состоит из обмена сообщениями JSON по HTTP. JSON является доминирующим форматом в REST API, поскольку он компактен, прост для понимания и имеет гибкий формат, который не требует предварительного описания схемы. Кроме того, разные клиенты могут использовать один и тот же API и читать нужные им данные.
Рассмотрим проект API , используя Swagger. Этот инструмент использует открытый формат для описания API в сочетании с веб-интерфейсом для визуализации информации об интерфейсах. Нет разделения между проектом и реализацией. Преимущество Swagger заключается в том, что API и документация также будут синхронизированы, при этом документация размещается вместе с API. Недостатком является то, что только разработчики API могут изменять структуру API. Так как документация генерируется из API, то нужно сначала создать каркас нашего API. Используется Spring Boot для разработки API и пакета Springfox для генерации документации.
Добавьте в ваш pom.xml зависимости swagger 2 и swagger-ui maven.
<dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger2</artifactId> <version>2.6.1</version> </dependency> <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-swagger-ui</artifactId> <version>2.5.0</version> </dependency>
Добавьте SwaggerConfig.java в проект со следующим содержанием:
package com.rks.catalog.configuration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger2.annotations.EnableSwagger2; @Configuration @EnableSwagger2 public class SwaggerConfig { @Bean public Docket api() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()).build(); } }
Эта конфигурация говорит Swagger сканировать все контроллеры и включать все URL-адреса, определенные в этих контроллерах для документации API.
После запуска приложения можно ознакомиться с документацией Swagger по API по URL-адресу:
http://localhost:8080/swagger-ui.html
Кликните на каждый API, чтобы изучить детали - URL, заголовки HTTP и тело HTTP. Полезной является кнопка "Try it out!", которая обеспечивает песочницу, позволяя пользователям поиграть с API, чтобы изучить его работу, прежде чем начать подключать в своих приложениях.
Тестирование
Функциональное тестирование API REST влечет за собой отправку HTTP-запросов и проверку ответов, чтобы была возможность проверить, работают ли API так, как мы ожидаем. REST использует HTTP в качестве транспорта, определяющий форматы запросов и ответов API. TCP / IP, в свою очередь, принимает HTTP-сообщения и решает, как их передавать по проводам. Представляем три набора инструментов для тестирования API на трех уровнях стека протоколов, а именно: клиенты REST для уровня REST, веб-отладчики для уровня HTTP и анализаторы пакетов для уровня TCP / IP.
-
Postman
- это REST-клиент, который позволяет нам тестировать REST API. Это позволяет нам:
- Создавать HTTP-запросы и генерировать эквивалентные команды cURL, которые можно использовать в скриптах.
- Создавать несколько сред для Dev, Test, Pre-Prod, так как каждая среда имеет разные конфигурации.
- Создавать коллекцию тестов, имеющую несколько тестов для каждой области продукта. Различные части теста могут быть параметризованы, что позволяет нам переключаться между средами.
- Создавать фрагменты кода в JavaScript для расширения тестов. Например, для подтверждения кодов возврата или установки переменных среды.
- Автоматизировать запуск тестов с помощью инструмента командной строки Newman.
- Импорт / экспорт тестовых коллекций и сред.
- cURL - это инструмент командной строки, который использует свой собственный стек HTTP и доступен кроссплатформенно.
curl -X POST \ http://localhost:8080/books \ -H 'Cache-Control: no-cache' \ -H 'Content-Type: application/json' \ -d '{ "id":"1", "author":"shakespeare", "title":"hamlet" }'
-
Burp
- это отладчик HTTP, который позволяет нам видеть веб-трафик, который проходит между клиентом и API. Он работает как прокси между клиентом и сервером, что позволяет нам перехватывать запрос и ответ и изменять их для создания сценариев, которые в противном случае сложно протестировать без изменения клиента. Burp - это набор инструментов, который в основном используется для тестирования безопасности, но также может быть очень полезен для тестирования API. Настройте свой Postman для отправки запроса на прокси Burp, а затем настройте Burp для перехвата запроса клиента и ответа сервера.
Перехватите запрос и ответ, как показано ниже.
- Wireshark - проверка некоторых функций API, например шифрования, сжатия и т. д., потребует от нас более глубокого изучения, чтобы увидеть, что отправляется и принимается в сети. Wireshark - это инструмент, который контролирует сетевой интерфейс и сохраняет копии всех TCP-пакетов, которые проходят через него. Трафик делится по слоям - HTTP, TCP, IP и т. д. Является помощником при устранении проблем, которые требуют более глубокого изучения, например, квитирование TLS.
Веб-Хостинг
В этом разделе мы рассмотрим некоторые функции протокола HTTP, которые при правильном использовании помогают предоставлять высокопроизводительные, высокодоступные, надежные и безопасные API. В частности, рассмотрим три части протокола HTTP - кэширование для производительности, DNS для высокой доступности и масштабируемости и TLS для безопасности транспорта.
-
Кэширование
- один из лучших способов повысить производительность клиента и снизить нагрузку на API. HTTP позволяет клиентам сохранять копию ресурса локально, отправляя в ответ заголовок кэширования, так что в следующий раз клиент отправляет HTTP-запрос на тот же ресурс, обслуживаемый из локального кэша. Это экономит сетевой трафик и вычислительную нагрузку на API.
- Кэширование срока действия HTTP 1.0 предоставляет заголовок Expires в ответе HTTP, указывающий время, когда ресурс истечет. Это может быть полезно для общего ресурса с фиксированным сроком действия.
- Кэширование срока действия HTTP 1.1 обеспечивает более гибкий контроль кэширования заголовка срока действия, который инструктирует клиента кэшировать ресурс в течение периода, установленного в значении max-age. Существует другое значение s-maxage, которое можно установить для посредников, например, кеширующий прокси.
- Кэширование проверки HTTP. При кэшировании существует проблема с клиентом, имеющим устаревший ресурс, или двумя клиентами, имеющими разные версии одного и того же ресурса. Если это неприемлемо или существуют персонализированные ресурсы, которые нельзя кэшировать, например, токены аутентификации, HTTP обеспечивает кэширование проверки. С помощью кэширования проверки HTTP предоставляет заголовки в ответном Etag или последней измененной временной метке. Если API возвращает один из двух заголовков, клиенты кэшируют его и включают в последующие вызовы GET для API.
GET http://api.endpoint.com/books If-none-match: "4v44ffgg1e"
Если ресурс не изменен, API вернет ответ 304 Not Modified без тела, и клиент сможет безопасно использовать свою кэшированную копию.
- DNS - система доменных имен находит IP-адреса для доменного имени, чтобы клиенты могли направить свой запрос на правильный сервер. Когда выполняется HTTP-запрос, клиенты сначала запрашивают DNS-сервер, чтобы найти адрес хоста, а затем отправляют запрос непосредственно на IP-адрес. DNS - это многоуровневая система, которая сильно кэшируется, чтобы гарантировать, что запросы не замедляются. Клиенты поддерживают кэш DNS, затем существуют промежуточные DNS-серверы, ведущие к серверу имен. DNS предоставляет CNAME (канонические имена) для доступа к различным частям сервера, например, API и веб-сервер могут быть размещены на одном сервере с двумя разными CNAME - api.endpoint.com и www.endpoint.com - или CNAME могут указывать на разные серверы. CNAME также позволяют нам отделять части нашего API. Для запросов HTTP GET у нас может быть отдельный CNAME для статических и транзакционных ресурсов, что позволит настроить внешний прокси-сервер для ресурсов, которые, как мы знаем, могут попасть в кэш. У нас также может быть CNAME для запросов HTTP POST для разделения операций чтения и записи, чтобы мы могли масштабировать их независимо. Или же мы можем обеспечить быструю полосу для приоритетных клиентов.
При использовании расширенного DNS, такого как Route53, одно CNAME вместо простого указания на один сервер может указывать на несколько серверов. Политику маршрутизации затем можно настроить для взвешенной маршрутизации, маршрутизации с задержкой или для отказоустойчивости.
- TLS - мы можем защитить наши API с помощью TLS, что позволяет нам обслуживать наш запрос по HTTPS. HTTPS работает по основному принципу безопасности пары ключей. Чтобы включить HTTPS в нашем API, нам нужен сертификат на нашем сервере, который содержит пару открытых и закрытых ключей. Сервер отправляет открытый ключ клиенту, который использует его для шифрования данных, а сервер использует свой закрытый ключ для его расшифровки. Когда клиент впервые подключается к конечной точке HTTPS, происходит «handshake», то есть клиент и сервер договариваются о том, как зашифровать трафик. Происходит обмен ключом, уникальным для сеанса, который используется для шифрования и дешифрования данных в течение всего сеанса. Во время первоначального «handshake» наблюдается снижение производительности из-за асимметричного шифрования, но как только соединение установлено, используется симметричное шифрование, происходящее довольно быстрое.
Чтобы прокси-серверы кэшировали трафик TLS, мы должны загрузить тот же сертификат, который используется для шифрования трафика. Прокси должен иметь возможность расшифровывать трафик, сохранять его в своем кеше, шифровать его тем же сертификатом и отправлять клиенту. Некоторые прокси-серверы не позволяют это. В этом случае решение состоит в том, чтобы иметь два CNAME - один для статических кэшируемых ресурсов по HTTP и второй для не кэшируемых персонализированных ресурсов, запросы которых по защищенному каналу TLS будут обслуживаться API напрямую.
Производительность
В этом разделе рассмотрим инструменты для нагрузочного тестирования нашего API для количественного определения объема трафика, с которым может справиться наша инфраструктура. Основная идея тестирования производительности заключается в одновременной отправке большого количества запросов в API и определении того, в какой момент производительность падает и дает сбой.
Вот вопросы, на которые нам нужны ответы:
- Какое время отклика может дать API при различных условиях нагрузки?
- Сколько одновременных запросов может обработать API без ошибок?
- Какая инфраструктура требуется для достижения желаемой производительности?
loader.io - это бесплатная облачная служба тестирования нагрузки, которая позволяет нам проводить стресс-тестирование наших API. Чтобы получить базовую производительность API, можно запускать различные виды нагрузочных тестов с увеличивающимися нагрузками, измеряемыми по количеству запросов в секунду для определения показателей производительности, количественно оцененные по ошибкам и времени отклика, для:
- Теста на выдерживание - средняя нагрузка за длительные периоды, например, на 48 часов при 1 запросе в секунду. Это позволит обнаружить любые утечки памяти или другие подобные скрытые ошибки.
- Нагрузочного теста - пиковая нагрузка, например, запуск 2K запросов в секунду с 6 экземплярами API.
- Стресс-теста - пиковая нагрузка при перегрузке, например, выполнение 10 000 запросов в секунду в течение 10 минут.
Это также позволяет определить инфраструктуру, которая позволит нам предоставлять API с требуемыми показателями производительности и линейным масштабированием нашего решения.
Возможность наблюдения
Развертывание API в производстве не означает, что мы можем забыть об API. Развертывание производства запускает еще один этап тестирования - тестирование в процессе производства, которое может выявить проблемы, не обнаруженные на более ранних этапах. Тестирование в производственном процессе включает в себя набор действий, объединенных в единое целое: наблюдаемость (включают ведение журнала), мониторинг, отслеживание. Инструменты для этих действий помогут диагностировать и решать проблемы, обнаруженные на производстве.
- Ведение журнала должно осуществляться разработчиками в явном виде с использованием предпочтительной среды ведения журнала и стандарта ведения журнала. Например, один оператор журнала для каждых 10 или более строк кода, если код сложный с уровнями журнала, разделенными на - 60% DEBUG, 25% INFO 10% WARN и 5% ERROR.
- Мониторинг - выполняется на более высоком уровне, чем регистрация. В то время как регистрация явно говорит нам о том, что происходит с API, мониторинг обеспечивает общее состояние API, используя общие метрики, предоставляемые платформой и самим API. Метрики, как правило, предоставляются агентом, развернутым на сервере, так же они могут быть частью решения и периодически собираются с помощью решения для мониторинга, развернутого удаленно.
В решение могут быть включены диагностические конечные точки, которые сообщают об общем состоянии API.
- Трассировка - Zipkin - это распределенная система трассировки. Помогает собирать временные данные, необходимые для устранения проблем с задержками в микросервисных архитектурах.
Включение централизованного ведения журнала охватывает ведение журнала и трассировку. Для мониторинга интересные метрики могут быть сохранены в хранилище временных рядов, таких как Prometheus, и визуализированы с использованием Grafana.
Управление
Инструменты управления API служат шлюзом, предоставляющий сервисы:
- Клиенты API обеспечивают себя, получая ключ API;
- Поставщики API настраивают DNS, кэширование, политики регулирования, управление версиями API и т.д.
Эти и другие функции доступны на AWS API Gateway.