В этом руководстве мы интегрируем SQS для отправки сообщения в лямбда-функцию в проекте Amplify с использованием Cloudformation.
Ссылка на репозиторий git: https://github.com/wahmd/sqs-with-lambda-using-aws-amplify
Интегрируйте пользовательский ресурс (SQS) с функцией amplify, чтобы отправка сообщения в очередь вызывала лямбда-выражение с сообщением о событии в теле.
Получите ту же полезную нагрузку внутри лямбда-функции.
Оглавление
- Почему этот учебник
- Базовая настройка проекта (из документации amplify):
- Добавьте функцию Lambda с помощью Amplify CLI:
- Добавление очереди SQS fifo
- Связывание очереди SQS с Lambda
- Добавление параметра (с использованием значения из другого стека)
- Неявный способ добавления параметра:
**<CATEGORY><RESOURCE_NAME><OUTPUTS_VARIABLE>**
- Явный способ добавления параметра:
- Добавить очередь как зависимость к лямбде (порядок создания ресурсов)
- Рабочая демонстрация
Важный совет:
Если во время обучения вы вносите какие-либо изменения в файл cloudformation, шаблона или параметров, обязательно выполните amplify env checkout
перед выполнением amplify push
. В противном случае cli не обнаружит изменения в течение amplify status
.
Почему этот учебник
SQS не генерируется клиентским интерфейсом amplify напрямую, как некоторые другие сервисы. например, мы можем добавить лямбду с помощью командыamplify add function
Но для добавления SQS у нас нет такой команды, как amplify add queue
и т. д.
Есть несколько способов добавить другие ресурсы, не поддерживаемые интерфейсом командной строки, в качестве Пользовательских ресурсов.
Amplify предоставляет два основных метода интеграции пользовательского ресурса в наше приложение Amplify.
- Используйте CDK для добавления пользовательских ресурсов AWS
- Используйте CloudFormation для добавления пользовательских ресурсов AWS
В первом вы можете написать свой пользовательский ресурс так же просто, как на Javascript, который cdk synth
преобразуется в облачное формирование.
Во втором вы просто предоставляете облачное формирование, которое развертывается при усилении push.
Оба этих метода просто великолепны. Однако в своем недавнем проекте я нашел еще один способ, которым хочу поделиться с вами, ребята. В этом методе я создал SQS, используя расширенную структуру папок и облачное формирование, не создавая отдельную папку для пользовательских ресурсов (как в приведенных выше методах).
Не нашел много в Интернете, поэтому просто поделился этим здесь для учебных целей.
Базовая настройка проекта (из документации amplify):
Сначала нам нужно инициализировать базовый бэкэнд amplify.
Для этого выполните все шаги в Предварительных требованиях и Настройка проекта полного стека, чтобы инициализировать пустой бэкэнд amplify.
Добавьте функцию Lambda с помощью Amplify CLI:
Теперь мы можем начать с добавления лямбда-функции, которая будет использоваться для опроса из очереди fifo.
Вы можете добавить лямбда-выражениеamplify add function
Это создаст лямбда-функцию AWS, которая будет использоваться для обработки сообщений из очереди.
Теперь мы видим, что function handleOrder
добавляется в папку amplify/backend
.
Это присутствует локально, поэтому нам нужно amplify push
его, чтобы эта лямбда создавалась в облаке.
После push
теперь вы можете перейти в консоль aws и проверить это. (убедитесь, что вы выбрали свой регион при просмотре, поскольку лямбда — это сервис, основанный на регионе, и он будет присутствовать только в вашем регионе)
Эта папка backend
содержит все ресурсы. Итак, если мы хотим добавить еще один (пользовательский) ресурс, нам нужно создать внутри него папку.
Добавление очереди SQS fifo
- Создайте новую папку внутри папки
backend
и назовите ееqueue
. («очередь» не является зарезервированным словом, вы можете назвать что угодно, но вам также необходимо обновить и другие файлы — поясните позже в руководстве). Это категория - Создайте папку и назовите ее
ordersQueue
(это ресурс (очередь)). - В любой папке ресурсов должны быть эти два файла:
template.yml
parameters.json
Итак, создайте эти файлы.
Я использую yml
для формирования облака.
в ресурсах добавьте ресурс типа SQS:Queue
как
Resources:
OrderQueue:
Type: AWS::SQS::Queue
Properties:
FifoQueue: true
ContentBasedDeduplication: true
QueueName:
Fn::Join:
- ''
- - orders-queue-
- Ref: env
- .fifo
Здесь я использую очередь «первым пришел, первым обслужен» (FIFO) с включенным ContentBasedDeduplication
.
Это также будет динамически генерировать имя очереди на основе среды выполнения.
Подробнее о встроенной функции Fn:join можно прочитать в документации.
Нам также нужно прикрепить политику SQS к этой очереди с разрешениями на отправку, получение, удаление и другие действия, такие как:
SQSPolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- Ref: OrderQueue
PolicyDocument:
Statement:
- Effect: Allow
Principal: '*'
Action:
- SQS:SendMessage
- SQS:ReceiveMessage
- SQS:DeleteMessage
- SQS:GetQueueAttributes
Resource:
Fn::GetAtt:
- OrderQueue
- Arn
Для простоты мы используем ‘*’. Эта политика позволяет всем участникам выполнять перечисленные действия в OrderQueue
.
Вместо этого в реальном приложении следует включать в очередь только те ресурсы или учетные записи, которым необходим доступ.
Итак, теперь наш полный template.yml
выглядит так:
AWSTemplateFormatVersion: '2010-09-09' Description: >- {"createdOn":"Windows","createdBy":"Amplify","createdWith":"7.3.6","stackType":"queue-SQS","metadata":{}} Parameters: env: Type: String Resources: OrderQueue: Type: AWS::SQS::Queue Properties: FifoQueue: true ContentBasedDeduplication: true QueueName: Fn::Join: - '' - - orders-queue- - Ref: env - .fifo
SQSPolicy: Type: AWS::SQS::QueuePolicy Properties: Queues: - Ref: OrderQueue PolicyDocument: Statement: - Effect: Allow Principal: '*' Action: - SQS:SendMessage - SQS:ReceiveMessage - SQS:DeleteMessage - SQS:GetQueueAttributes Resource: Fn::GetAtt: - OrderQueue - Arn Outputs: QueueURL: Description: URL of new Amazon SQS Queue Value: Ref: OrderQueue QueueARN: Description: ARN of new Amazon SQS Queue Value: Fn::GetAtt: - OrderQueue - Arn QueueName: Description: Name new Amazon SQS Queue Value: Fn::GetAtt: - OrderQueue - QueueName
- Поместите пустой объект в
parameters.json
как:{}
- Включите
queue
в папкуbackend-config
. Потому что, если ваш ресурс не указан вbackend-config
, он не появится вamplify status
и, следовательно, не будет отправлен в облако.
{
"function": {
"handleOrder": {
"build": true,
"providerPlugin": "awscloudformation",
"service": "Lambda",
}
},
"queue": {
"ordersQueue": {
"providerPlugin": "awscloudformation",
"service": "SQS"
}
}
}
- Теперь сохраните изменения
- Сообщите CLI о нашей пользовательской категории и ресурсе, проверив текущую среду:
amplify env checkout <env-name>
- Повторите
amplify push
, чтобы получить очередь в облаке. - Мы можем видеть нашу очередь на консоли
- Если все загружается в облако без проблем, вы можете перейти к следующей части.
Связывание очереди SQS с Lambda
Теперь у нас есть queue
и handleOrder в облаке, но оба они не настроены. Мы настроили его таким образом, что если SQS получает сообщение, оно отправляется в лямбду как событие.
Это идеальный случай для типа EventSourceMapping
, который в основном отображает событие из источника (кинез, SQS все, что создает событие и т. д.). к лямбда-функции.
Поэтому мы добавляем это в формирование облака нашей функции handleOrder
в разделе Resources
.
"LambdaFunctionSQSMapping": {
"Type": "AWS::Lambda::EventSourceMapping",
"Properties": {
"BatchSize": 1,
"Enabled": true,
"EventSourceArn": {
"Ref": "queueordersQueueQueueARN"
},
"FunctionName": {
"Ref": "LambdaFunction"
}
}
}
путь к файлу: amplify/backend/function/handleOrder/handleOrder-cloudformation-template.json
Здесь важными атрибутами, которые следует учитывать, являются:
EventSourceArn
— это уникальный идентифицируемый номер источника, из которого будет поступать событие.FunctionName
— Имя функции, которая будет вызываться при наступлении события.
Добавление параметра (с использованием значения из другого стека)
Здесь у нас в настоящее время нет queueARN внутри этого файла. Мы можем получить к нему доступ, используя parameters
и Outputs
возможности стеков.
Мы экспортируем QueueARN
из нашей очереди в ее template.yml
.
Есть два способа использования параметров.
- неявный — автоматически усиливать выбор, если соблюдается структура каталогов)
- явный — определите, из какого именно ресурса, какое значение получите с помощью встроенных функций.
Неявный способ добавления параметра:
- Включите параметр
queueordersQueueQueueARN
в лямбда-облако как:
"queueordersQueueQueueARN": {
"Type": "String"
}
Структура имени параметра очень важна, так как amplify автоматически выбирает ее, если используется правильно.
**<CATEGORY><RESOURCE_NAME><OUTPUTS_VARIABLE>**
Структура каталогов:
amplify
├── backend
│ ├── function
│ │ └── handleOrder
│ ├── queue
│ │ └── ordersQueue
│ │ ├── template.yml
│ │ └── parameters.json
пример: очередь ордеровQueueQueueARN
Явный способ добавления параметра:
Наряду с неявным способом вы также определяете в parameters.json
, откуда именно вы получите это значение.
- Включить в файл
amplify/backend/function/handleOrder/parameters.json
{
"queueordersQueueQueueARN": {
"Fn::GetAtt": ["ordersQueue", "Outputs.QueueARN"]
}
}
Здесь GetAtt
извлекает QueueARN
из ресурса ordersQueue
, который экспортируется из стека с использованием Outputs
.
Добавить очередь как зависимость к лямбде (порядок создания ресурсов)
В backend-config
все ресурсы выводятся и генерируются параллельно, если между ними нет зависимости.
Если мы попытаемся push
запустить наше текущее приложение, мы получим сообщение об ошибке:An error occur during the push operation: Template error: instance of Fn:GetAtt references undefined resource ordersQueue
Мы получаем это в parameters.json
, когда пытаемся получить доступ к QueueARN
из его экспорта.
orderQueue имеет номер undefined
, и доступ к одному из его экспортов приводит к ошибке.
Почему orderQueue не определен?
Поскольку облако создает очередь и лямбду параллельно, но поскольку лямбда зависит от очереди (мы используем выходные данные очереди в лямбде), мы должны сообщить облаку, что создавать лямбда только тогда, когда очередь полностью создана и готова
Мы можем определить порядок, в котором ресурсы будут создаваться в облаке в backend-config.json
, следующим образом:
- обновить
backend-config.json
как:
{
"function": {
"handleOrder": {
"build": true,
"providerPlugin": "awscloudformation",
"service": "Lambda",
"dependsOn": [
{
"category": "queue",
"resourceName": "ordersQueue",
"attributes": ["QueueARN"]
}
]
}
},
"queue": {
"ordersQueue": {
"providerPlugin": "awscloudformation",
"service": "SQS"
}
}
}
Здесь, в dependsOn
, мы определяем, что текущий ресурс не должен создаваться, если все ресурсы в массиве dependsOn
не готовы, поскольку он имеет зависимость. Сначала создайте зависимые ресурсы, затем создайте исходный ресурс.
- Do
amplfiy env checkout <INSERT_YOUR_ENV>
- Do
amplify push -y
После успешного запуска у вас будет все готово для демонстрации.
Рабочая демонстрация
Мы видим, что отправка сообщения в очередь вызывает лямбду с сообщением о событии в теле.
- ✅ Получите ту же полезную нагрузку внутри лямбда-функции.
Если вам это понравилось, ⭐ этот репозиторий по адресу:
https://github.com/wahmd/sqs-with-lambda-using-aws-amplify