Блог Amazon Web Services
Строим API быстрее, дешевле и лучше – HTTP API для Amazon API Gateway
Оригинал статьи: ссылка (Eric Johnson, Senior Developer Advocate)
В июле 2015 года AWS объявила о запуске Amazon API Gateway. Этот сервис позволил разработчикам быстро создавать безопасные, масштабируемые API перед различными типами архитектур. С тех пор команда разработчиков API Gateway постоянно добавляла новые функции и сервисы для клиентов.
В начале 2019 года команда разработки протестировали новые языки программирования и новые технологии, применили опыт, полученный при создании REST и WebSocket API, и внимательно изучили отзывы клиентов. В результате был создан HTTP API для Amazon API Gateway — сервис, созданный с нуля, чтобы быть быстрее, дешевле и проще в использовании. Если очень коротко, HTTP API предлагает лучшее решение для построения API. Если вы строите API и HTTP API соответствует вашим требованиям, то с него стоит начать.
Быстрее
В большинстве случаев использование HTTP API обеспечивает снижение задержек до 60%. Разработчики стремятся создавать приложения с минимальными задержками и максимальной функциональностью. Они понимают, что каждый сервис, участвующий в обработке запроса, может создавать задержку.
Понимая это, HTTP API создан для того, чтобы снизить добавочные задержки от API Gateway. Если объединить данные запросов (request) и ответов (response), HTTP API вносит менее 10мс дополнительной задержки для 99% всех запросов (p99).
Дешевле
Одним из основных принципов Amazon является бережливость. Мы верим, что мы должны делать всё эффективно и экономно, передавая сэкономленное нашим клиентам. Благодаря доступности новых технологий и опыту использования API Gateway в течение почти пяти лет, мы создали HTTP API для более эффективной работы.
На рисунке 3 показано сравнение стоимости 100 миллионов, 500 миллионов и 1 миллиарда запросов в месяц (используются цены для региона us-east-1). В целом, HTTP API как минимум на 71% дешевле по сравнению с API Gateway REST API.
Проще
Команда API Gateway сделала пользовательский интерфейс для HTTP API более интуитивным и простым в использовании.
Одним из примеров упрощения является процесс конфигурации cross-origin resource sharing (CORS). CORS обеспечивает безопасность, контролируя междоменный доступ к серверам, и бывает сложным для понимания и настройки. HTTP API позволяет разработчику быстро настроить параметры CORS с помощью простого и понятного пользовательского интерфейса. Такой же подход во всем пользовательском интерфейсе создает простой подход к построению API.
Новые возможности
На AWS re:Invent 2019 была анонсирована бета-версия HTTP API с такими мощными функциями, как JWT авторизаторы, стадии автоматического разворачивания и упрощенные маршрутные интеграции. Сегодня HTTP API доступен для промышленной эксплуатации (GA) с большим количеством функций, которые помогают разработчикам строить API быстрее, дешевле и лучше.
Интеграция с частными ресурсами
HTTP API теперь предлагают разработчикам возможность интеграции с защищенными ресурсами в Amazon VPC. При запуске приложений в контейнерах с помощью сервисов Amazon Elastic Container Service (ECS) или Amazon Elastic Kubernetes Service (EKS), их базовые кластеры Amazon EC2 должны находиться внутри VPC. Хотя эти приложения можно сделать публично доступными с помощью Elastic Load Balancing, разработчики могут также подключить HTTP API в качестве интерфейса перед своими приложениями.
Для интеграции с частными ресурсами вам понадобится создать VPC Link. VPC Link используют платформу виртуализации сетевых функций AWS Hyperplane, которая так же используется для Network Load Balancer и NAT Gateway. С помощью этой платформы несколько интерфейсов HTTP API могут использовать один VPC Link. Аналогично, несколько интерфейсов REST API могут использовать один VPC Link для REST API.
После создания VPC Link вы можете подключить HTTP API к Network Load Balancer (NLB), Application Load Balancer (ALB), или к службе обнаружения ресурсов, AWS Cloud Map.
Совместное использование пользовательских доменов
Amazon API Gateway теперь позволяет совместное использование пользовательских доменов для REST API и HTTP API. Такая гибкость позволяет разработчикам использовать разные типы API-интерфейсов (REST и HTTP) в одном приложении.
Ранее при создании приложений, требующих постоянного доменного имени, разработчики могли использовать только один тип API. Поскольку приложениям часто требуются функции, доступные только в REST, REST API выбирали чаще всего. Теперь вы можете распределять маршруты в рамках одного домена между HTTP API и REST API, в зависимости от требований к функциям API-интерфейсов.
Ограничение количества запросов
HTTP API теперь предлагают возможность гранулярно ограничивать количество запросов в зависимости от фазы разворачивания API, и от маршрута запроса. Ограничение запросов к API часто игнорируют, в то время как эта функция является критичной для работоспособности API. По умолчанию, API Gateway ограничивает усредненную частоту запросов до 10,000 запросов в секунду (rps), и кратковременные всплески — до 5,000 запросов в секунду. Эти лимиты могут быть подняты с помощью AWS Service Quotas.
У HTTP API есть концепция фаз разворачивания, которые могут быть использованы для различных целей. Приложения могут быть в фазах dev, beta и prod на одном и том же API. Кроме того, для обратной совместимости, вы можете настроить несколько prod фаз одного и того же API. Каждая фаза имеет опциональные настройки кратковременного и усредненного ограничений частоты запросов, которые перекрывают стандартную настройку 10 000 rps на уровне аккаунта.
Ограничение количества запросов также можно установить на уровне маршрута. Маршрут — это комбинация пути и метода. Например, маршрут может состоять из выбора GET-метода на корневом пути (/). На момент написания этой статьи ограничение на уровне маршрута может быть установлено с помощью AWS Command Line Interface (CLI) или AWS SDK. Для задания ограничения на маршруте / [ANY] на этапе $default используйте следующую команду CLI:
aws apigatewayv2 update-stage --api-id <your API ID> --stage-name $default --route-settings '{"ANY /": {"ThrottlingBurstLimit":1000, "ThrottlingRateLimit":2000}}'
Переменные фазы разворачивания
HTTP API теперь поддерживают использование переменных фазы разворачивания для передачи динамических данных в бэкенд или даже для определения самой интеграции. Когда в HTTP API определена фаза, можно задать ее собственный путь интеграции с бэкендом. В таблице показан домен с разными путями для различных фаз:
Фаза | Путь |
$default | www.mydomain.com |
dev | www.mydomain.com/dev |
beta | www.mydomain.com/beta |
Когда вы вызываете ссылку dev фазы, переменные dev фазы передаются в бэкенд внутри объекта события. Бэкенд использует их при обработке запроса. Хотя не рекомендуется передавать пароли и ключи доступа через такие переменные, в них можно задавать различные параметры, например эндпойнты или переключатели feature-toggle.
С помощью переменных фазы также можно динамически определять бэкенд. Например, если API использует одну функцию AWS Lambda для prod, и другую для test – вы можете использовать переменные фазы для динамической маршрутизации к нужной Lambda функции, как показано ниже:
При построении динамических интеграций также важно вовремя обновлять права доступа. HTTP API автоматически добавляет права на вызов Lambda функции, когда эта функция – единственная в интеграции. Однако при использовании нескольких функций необходимо создавать и управлять ролью вручную. Для этого нужно сначала отключить настройку «Grant API Gateway permission to invoke your Lambda function», а потом указать пользовательскую роль с соответствующими правами.
Формат сообщений Lambda функций версии 2.0
HTTP API теперь поддерживает обновленный формат данных события и формат ответа использования Lambda функций. Версия 2.0 упрощает формат объекта события, отправляемого на функцию Lambda. Вот сравнение объекта события, который отправляется в функцию Lambda в версиях 1.0 и 2.0:
Версия 1.0
{
"version": "1.0",
"resource": "/Echo",
"path": "/Echo",
"httpMethod": "GET",
"headers": {
"Content-Length": "0",
"Host": "0000000000.execute-api.us-east-1.amazonaws.com",
"User-Agent": "TestClient",
"X-Amzn-Trace-Id": "Root=1-5e6ab926-933e1530e55773a0709dfaa6",
"X-Forwarded-For": "1.1.1.1",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https",
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"cache-control": "no-cache",
"clientInformation": "private",
"cookie": "Cookie_2=value; Cookie_3=value; Cookie_4=value"
},
"multiValueHeaders": {
"Content-Length": [
"0"
],
"Host": [
"0000000000.execute-api.us-east-1.amazonaws.com"
],
"X-Amzn-Trace-Id": [
"Root=1-5e6ab926-933e1530e55773a0709dfaa6"
],
"X-Forwarded-For": [
"1.1.1.1"
],
"X-Forwarded-Port": [
"443"
],
"X-Forwarded-Proto": [
"https"
],
"accept": [
"*/*"
],
"accept-encoding": [
"gzip, deflate, br"
],
"cache-control": [
"no-cache"
],
"clientInformation": [
"public",
"private"
],
"cookie": [
"Cookie_2=value; Cookie_3=value; Cookie_4=value"
]
},
"queryStringParameters": {
"getValueFor": "newClient"
},
"multiValueQueryStringParameters": {
"getValueFor": [
"newClient"
]
},
"requestContext": {
"accountId": "0000000000",
"apiId": "0000000000",
"domainName": "0000000000.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "0000000000",
"extendedRequestId": "JTHd9j2EoAMEPEA=",
"httpMethod": "GET",
"identity": {
"accessKey": null,
"accountId": null,
"caller": null,
"cognitoAuthenticationProvider": null,
"cognitoAuthenticationType": null,
"cognitoIdentityId": null,
"cognitoIdentityPoolId": null,
"principalOrgId": null,
"sourceIp": "1.1.1.1",
"user": null,
"userAgent": "TestClient",
"userArn": null
},
"path": "/Echo",
"protocol": "HTTP/1.1",
"requestId": "JTHd9j2EoAMEPEA=",
"requestTime": "12/Mar/2020:22:35:18 +0000",
"requestTimeEpoch": 1584052518094,
"resourceId": null,
"resourcePath": "/Echo",
"stage": "$default"
},
"pathParameters": null,
"stageVariables": null,
"body": null,
"isBase64Encoded": true
}
Версия 2.0
{
"version": "2.0",
"routeKey": "ANY /Echo",
"rawPath": "/Echo",
"rawQueryString": "getValueFor=newClient",
"cookies": [
"Cookie_2=value",
"Cookie_3=value",
"Cookie_4=value"
],
"headers": {
"accept": "*/*",
"accept-encoding": "gzip, deflate, br",
"cache-control": "no-cache",
"clientinformation": "public,private",
"content-length": "0",
"host": "0000000000.execute-api.us-east-1.amazonaws.com",
"user-agent": "TestClient",
"x-amzn-trace-id": "Root=1-5e6ab967-cfe253ce6f8b90986a678c40",
"x-forwarded-for": "1.1.1.1",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"queryStringParameters": {
"getValueFor": "newClient"
},
"requestContext": {
"accountId": "0000000000",
"apiId": "0000000000",
"domainName": "0000000000.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "0000000000",
"http": {
"method": "GET",
"path": "/Echo",
"protocol": "HTTP/1.1",
"sourceIp": "1.1.1.1",
"userAgent": "TestClient"
},
"requestId": "JTHoQgr2oAMEPMg=",
"routeId": "47matwk",
"routeKey": "ANY /Echo",
"stage": "$default",
"time": "12/Mar/2020:22:36:23 +0000",
"timeEpoch": 1584052583903
},
"isBase64Encoded": true
}
Кроме того, версия 2.0 позволяет более гибко определять формат объекта ответа Lambda функции. Ранее было необходимо возвращать ответ такого формата:
{
"statusCode": 200,
"body":
{
"Name": "Eric Johnson",
"TwitterHandle": "@edjgeek"
},
Headers: {
"Access-Control-Allow-Origin": "https://amazon.com"
}
}
При использовании версии 2.0 ответ проще:
{
"Name": "Eric Johnson",
"TwitterHandle": "@edjgeek"
}
Когда HTTP API получает ответ, он использует настройки CORS и коды ответа Lambda функции, чтобы заполнить недостающие данные.
По умолчанию новые интеграции с Lambda функциями используют версию 2.0. Вы можете это изменить в меню настроек интеграции в разделе Расширенные настройки (Advanced settings). Выбор версии распространяется как на формат объекта события, так и на формат ответа. При выборе версии 1.0 в Lambda функцию передается старый формат события, и нужно вернуть полный объект ответа.
Поддержка OpenAPI/Swagger
HTTP API теперь поддерживают импорт конфигурационных файлов Swagger или OpenAPI. Это упрощает переход с других сервисов API Gateway на HTTP API. При импорте конфигурационного файла HTTP API реализует все поддерживаемые функции и сообщает о любых функциях, которые в данный момент не поддерживаются.
Поддержка AWS Serverless Application Model (SAM)
На момент написания этой статьи, AWS Serverless Application Model framework (SAM) поддерживает большинство функций, выпущенных в бета-версии на re:Invent 2019.
Заключение
В течение почти пяти лет Amazon API Gateway позволяет разработчикам создавать высокомасштабируемые и долговечные API. Он позволил вынести из кода приложений в управляемый сервис такие задачи, как авторизация, ограничение количества запросов и проверка валидности данных. С запуском HTTP API для Amazon API Gateway разработчики теперь могут использовать этот мощный сервис быстрее, дешевле и лучше.