Аннотация
В этой статье я попытался описать шаги и артефакты, необходимые для реализации стратегии управления версиями REST API на основе Amazon API Gateway.
Вступление
Существует требование для управления версиями REST API в одном из наших проектов. Эти REST API должны быть достаточно универсальными для поддержки нескольких арендаторов и нескольких версий. Поскольку эти API будут использоваться несколькими клиентами, существует возможность, когда два разных клиента могут использовать две разные версии API одновременно.
Поскольку мы реализуем наш API с помощью сервиса Amazon API Gateway, и мы хотим реализовать рекомендуемый наилучший подход. Я пытался найти лучшую стратегию управления версиями с использованием AWS API Gateway и Lambda. Проведя день в поиске, я понимаю, что существует три грубых стратегии для версии REST API. 1) Создайте совершенно новый API с добавлением номера версии в конце (например, www.mydomain.com/ordersV1, www.mydomain.com/ordersV2 примерно так), 2) Поместите индикатор версии в путь к ресурсу (например, www .mydomain.com / api / v1 / xxx, www.mydomain.com/api/v2/xxx) — это традиционный подход. и 3) Создать совершенно новый домен для новой версии (v1.api.mysite.com, v2.api.mysite.com). Мы должны выбрать наш подход из этих трех стратегий.
Решение Подход
В AWS API Gateway есть опция с именем Stage Variables. В представлении Integration Request мы можем предоставить имя переменной рабочей области ( ${stageVariables.<stage variable name> }
) вместо фактического имени функции Lambda. Во время развертывания переменная stage может содержать другую версию Lambda (или псевдоним), так что в зависимости от активированного ресурса (/ api / v1 / getOrders), промежуточной среды (dev, prod и т. Д.) И лямбда-имени с версией, определенной в stage Переменная API-шлюз может выбрать соответствующую функцию для вызова. Мы решили использовать эту функцию в соответствии с традиционным подходом к управлению версиями, то есть к управлению версиями на основе пути к ресурсам. В следующем разделе объясняются подробности этапов реализации этого подхода вручную.
Детали решения
Я создал одну простую лямбда-функцию NodeJs с двумя версиями, а затем создал ресурсы API шлюза AWS для запуска этих версий. Все описанные здесь шаги выполняются вручную. Позже мы установим AWS CodePipeline для развертывания версии (или псевдонима) Lambda, но в соответствии с текущим планом мы не будем автоматизировать развертывание API. Это будет сделано вручную в соответствии с дорожной картой.
1. Создайте одну лямбда-функцию nodejs getOrders
.
2. Сгенерируйте две версии функции с некоторыми изменениями в ответе JSON.
3. Создайте тестовое событие для проверки лямбды. Поскольку у меня есть план по созданию LAMBDA_PROXY
интеграции типов в API Gateway, я выбираю шаблон API Gateway AWS Proxy . Запрос JSON тестового события приведен ниже.
{
"body": "{\"test\":\"body\"}",
"resource": "/dev/v1/orders",
"requestContext": {
"resourceId": "123456",
"apiId": "1234567890",
"resourcePath": "/dev/v1/orders",
"httpMethod": "GET",
"requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
"accountId": "123456789012",
"identity": {
"apiKey": null,
"userArn": null,
"cognitoAuthenticationType": null,
"caller": null,
"userAgent": "Custom User Agent String",
"user": null,
"cognitoIdentityPoolId": null,
"cognitoIdentityId": null,
"cognitoAuthenticationProvider": null,
"sourceIp": "127.0.0.1",
"accountId": null
},
"stage": "dev"
},
"queryStringParameters": {
"start":"2015-10-01T00:00:00Z",
"end":"2015-10-04T00:00:00Z"
},
"headers": {
"Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
"Accept-Language": "en-US,en;.8",
"CloudFront-Is-Desktop-Viewer": "true",
"CloudFront-Is-SmartTV-Viewer": "false",
"CloudFront-Is-Mobile-Viewer": "false",
"X-Forwarded-For": "127.0.0.1, 127.0.0.2",
"CloudFront-Viewer-Country": "US",
"Accept": "text/html,application/xhtml+xml,application/xml;.9,image/webp,*/*;.8",
"Upgrade-Insecure-Requests": "1",
"X-Forwarded-Port": "443",
"Host": "1234567890.execute-api.us-east-2.amazonaws.com",
"X-Forwarded-Proto": "https",
"X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
"CloudFront-Is-Tablet-Viewer": "false",
"Cache-Control": "",
"User-Agent": "Custom User Agent String",
"CloudFront-Forwarded-Proto": "https",
"Accept-Encoding": "gzip, deflate, sdch"
},
"pathParameters": {
"proxy": "path/to/resource"
},
"httpMethod": "GET",
"stageVariables": {
"v1fn": "getOrders:1",
"v2fn":"getOrders:2"
},
"path": "/path/to/resource"
}
4. Следуя минимальным изменениям, которые я сделал для проверки лямбда-функции:
- Обновление
resource
иresourcePath
с запланированным путем ресурса шлюза API (/dev/v<#>/orders
). httpMethod
будетGET
для этого POC.stage
будетdev
.queryStringParameters
естьstart
иend
отметка времени.- У меня есть план создать две версии API, каждая из которых будет указывать на соответствующую версию Lambda в среде разработки. Для этого я создал два
stageVariables
(v1fn
иv2fn
) с <имя функции>: <номер версии> (getOrders:1
&getOrders:2
)
Вот и все. Я сделал с созданием тестового события. Если я выполню событие, я увижу, что функция getOrders возвращает правильный вывод.
5. Теперь из меню Amazon API Gateway создайте API со следующим путем для двух версий API. Для версии 1 это так /v1/orders
, а для версии 2 это так /v2/orders
.
6. Тип запроса интеграции LAMBDA_PROXY
должен пройти queryStringParameters
без проблем.
7. Чтобы реализовать LAMBDA_PROXY
тип интеграции, нам нужно выполнить следующую настройку в представлении запроса интеграции .
Примечание. Здесь вместо того, чтобы давать имя лямбда-функции, я указываю ${stageVariables.<stage-variable-name>}
динамически выбирать другую версию функции (или псевдоним).
8. Такая же настройка необходима для /v2/orders
ресурса.
9. Теперь мы можем протестировать оба API-интерфейса из мастера тестирования API.
Примечание: здесь мы должны ввести значение переменной stage во время теста (например, для v2fn
него getOrders:2
), иначе API будет работать некорректно.
10. Теперь разверните API на стадии разработки. URI API для разных версий:
https://xxxxxxxxxx.execute-api.xxxxxxxxx.amazonaws.com/dev/v1/orders
https://xxxxxxxxxx.execute-api.xxxxxxxxx.amazonaws.com/dev/v2/orders
Где ресурсы /dev/v1/orders
и /dev/v2/orders
соответственно.
Примечание. У нас есть план развертывания лямбда-кода с использованием AWS CodePipeline. Поскольку у нас ограниченное количество API, мы вручную создадим API из консоли Amazon API Gateway.
Заключение
Ниже приведены общие проблемы, которые мы рассмотрели в ходе этой реализации.
вопросы |
Как мы обращаемся |
Нет изоляции. Если у нас есть ошибка в коде v1, которая может быть использована, все наши экземпляры уязвимы. |
Существуют отдельные коды для каждой из функций Lambda, и, поскольку это подход функционального программирования, между версиями нет общего кода. |
Ограничения развития. Нам нужно поддерживать всю кодовую базу, чтобы убедиться, что «v1» и «v2» прекрасно живут вместе. Рассмотрим ситуацию, когда некоторая зависимость используется как в «v1», так и в «v2», но требует определенных разных версий. |
Коды лямбда-функций v1 и v2 и соответствующие им зависимости являются взаимоисключающими, поэтому конфликта не будет. |
Технология блокировки. Нельзя или очень сложно иметь «v1» в C # и «v2» в Python. |
Это может быть невозможно при использовании лямбда-реализации, потому что между лямбда-функцией и языком программирования существует соотношение 1: 1. |
Планирование и мониторинг мощностей. Трудно понять, сколько ресурсов потребляют вызовы «v1» против «v2». |
Мы можем осуществлять мониторинг на основе полного и регулярного пути к ресурсам на основе выражений. |
Подходы, основанные на доменных именах и API-именах, также могут быть возможным решением, но поскольку Amazon предлагает нам такую большую гибкость, мы с энтузиазмом реализуем управление версиями с его самым глубоким компонентом и можем поддерживать традиционный дух.