#triggers #aws-lambda #delay #amazon-sqs #aws-sam
#триггеры #aws-lambda #задержка #amazon-sqs #aws-sam
Вопрос:
У меня есть лямбда-код, настроенный для запуска при публикации сообщений в очереди SQS. Вот шаблон SAM для развертывания.
MyQueue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 180
DelaySeconds: 90
MyLambda:
Type: AWS::Serverless::Function
Properties:
CodeUri: ../pathToCode
Handler: index.handler
Events:
MySQSEvent:
Type: SQS
Properties:
Queue: !GetAtt MyQueue.Arn
Я использую DelaySeconds
свойство AWS::SQS::QUEUE
, которое, по-видимому, не работает. Мой лямбда-код выполняется, как только сообщение публикуется в очереди. Как я могу добавить в него задержку?
Комментарии:
1. Что ж, это работает так, как ожидалось.
DelaySeconds
задержит доставку сообщения в очередь на указанный промежуток времени. Это не означает, что оно будет невидимым в течение этого периода времени, поэтому, как только сообщение попадает в очередь, ваша лямбда-функция пытается его перехватить. Я боюсь, что то, чего вы пытаетесь достичь, невозможно. Я действительно не вижу большой пользы в этом. Возможно, если вы немного реорганизуете свою архитектуру, вам не понадобятся эти типы обходных путей2. @ThalesMinussi спасибо за ответ. Мой вариант использования таков: мне нужно выполнить какое-то действие в другом лямбда-выражении через минуту после выполнения определенной задачи. Итак, я отправляю сообщение в очередь (запуск другого лямбда-кода), надеясь, что оно будет выполнено через минуту. Имеет ли это какой-либо смысл?
3. Боюсь, вы не сможете добиться этого с помощью SQS. Один из способов, который я вижу, чтобы сделать это (не слишком задумываясь), — создать элемент в DynamoDB, содержащий сообщение. Затем вы могли бы подключить событие cloud watch к Lambda, например, опрашивающему эту таблицу DynamoDB каждые 10 секунд, поэтому каждый раз, когда он видит новый элемент, который еще не запущен, вы затем вызываете свой Lambda. Теперь я возвращаю вам вопрос: имеет ли это смысл?
4. Я сказал 10 секунд, но это было случайное число. Если вы хотите видеть это каждую минуту, то запускайте событие cloud watch каждую минуту. Однако он может попасть в какую-то серую область, и ваш товар не будет получен в течение 1 минуты и 59 секунд. Если вы можете ждать так долго, я думаю, все должно быть в порядке. Вы также можете добавить столбец в свою таблицу DynamoDB, в котором содержится информация о том, КОГДА оно должно выполняться. Поэтому, если вы запускаете событие CloudWatch и item.shouldRunAt позже текущего времени, ничего не делайте и дождитесь следующего выполнения
5. Это может сработать, как насчет функции step? Что, если я создам пошаговую функцию, первым шагом которой будет задержка в одну минуту, и после этого мой лямбда-код может быть выполнен.
Ответ №1:
ОТРЕДАКТИРОВАНО:
Есть 3 способа, которые вы можете рассмотреть для задержки доставки сообщения из SQS в Lambda:
- Настройте
DelaySeconds
очередь так, чтобы новые сообщения были невидимы для потребителей (таких как ваша Lambda) в течение определенного периода времени, до 15 минут - Настройте
MaximumBatchingWindowInSeconds
в своем источнике событий Lambda (триггер). Ваш Lambda может агрегировать сообщения в течение указанной продолжительности (до 5 минут) или до достиженияBatchSize
(до 10 000 сообщений, по умолчанию 10). Этот параметр настраивает максимальное время ожидания для сообщений, в то время как для некоторых сообщений может вообще не быть ожидания (при достижении максимального времени / размера окна). - Используйте конечный автомат пошаговых функций (с
Wait
состоянием), как предлагалось в исходном ответе. Это дает максимальную гибкость и возможность ждать до 1 года.
Оригинальный ответ:
Лучшее решение — использовать пошаговые функции AWS.
Лямбда-код, запускаемый SQS, должен выполнять конечный автомат, где первым шагом является требуемое количество времени ожидания, а вторым — вызов лямбды.
Комментарии:
1. Я пришел к такому же выводу. Спасибо @Ronyis
2. @AffanShahab Возможно, вы захотите проверить функцию пакетного окна. Смотрите мой ответ.
3. @ronyis: Я хотел бы понять, почему пошаговые функции являются лучшим решением, чем SQS delay с lambda?
4. @systemdebt обновил ответ — зависит от варианта использования
Ответ №2:
В 2021 году лучшим ответом будет использование новой функции SQS «пакетное окно»:
Используя это, вы можете разрешить очереди SQS собирать сообщения в течение 5 минут, прежде чем будет вызвана функция Lambda.
Комментарии:
1. Спасибо за обновленный ответ, прошло много времени с тех пор, как я это сделал, и в настоящее время не работает над этим проектом. Я проверю это при необходимости в будущем
2. MaximumBatchingWindowInSeconds говорит: «Максимальное количество времени в секундах, которое Лямбда тратит на сбор записей перед вызовом функции».. Свойство используется для ожидания достижения размера пакета. Если вам нужно подождать X минут для выполнения каждого сообщения в очереди, это решение не сработает, например, если размер пакета равен 10 и накоплено 9 сообщений, когда придет следующее сообщение, выполнение будет немедленным, не дожидаясь необходимой задержки в x минут.
Ответ №3:
Секунды задержки: это задерживает вызов получения сообщения всякий раз, когда вы опрашиваете очередь. Но всякий раз, когда вы помещаете это сообщение в очередь, сообщение немедленно вставляется.
Если вы хотите, чтобы ваша лямбда выполнялась через определенный интервал после запуска триггера, установите режим ожидания (n) перед началом выполнения и увеличьте время ожидания лямбды, если требуется. На данный момент нет прямого способа отложить запуск, ваш лямбда-код будет запущен, как только сообщение окажется в очереди.
Комментарии:
1. Это не оптимальное решение, потому что стоимость lambda привязана ко времени выполнения
2. @Nikaidoh абсолютно правильно. Это добавит накладные расходы, основанные на объеме памяти, используемой за этот конкретный промежуток времени.