Как запустить lambda с некоторой задержкой при публикации сообщения в SQS?

#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:

  1. Настройте DelaySeconds очередь так, чтобы новые сообщения были невидимы для потребителей (таких как ваша Lambda) в течение определенного периода времени, до 15 минут
  2. Настройте MaximumBatchingWindowInSeconds в своем источнике событий Lambda (триггер). Ваш Lambda может агрегировать сообщения в течение указанной продолжительности (до 5 минут) или до достижения BatchSize (до 10 000 сообщений, по умолчанию 10). Этот параметр настраивает максимальное время ожидания для сообщений, в то время как для некоторых сообщений может вообще не быть ожидания (при достижении максимального времени / размера окна).
  3. Используйте конечный автомат пошаговых функций (с Wait состоянием), как предлагалось в исходном ответе. Это дает максимальную гибкость и возможность ждать до 1 года.

Оригинальный ответ:

Лучшее решение — использовать пошаговые функции AWS.

Лямбда-код, запускаемый SQS, должен выполнять конечный автомат, где первым шагом является требуемое количество времени ожидания, а вторым — вызов лямбды.

Комментарии:

1. Я пришел к такому же выводу. Спасибо @Ronyis

2. @AffanShahab Возможно, вы захотите проверить функцию пакетного окна. Смотрите мой ответ.

3. @ronyis: Я хотел бы понять, почему пошаговые функции являются лучшим решением, чем SQS delay с lambda?

4. @systemdebt обновил ответ — зависит от варианта использования

Ответ №2:

В 2021 году лучшим ответом будет использование новой функции SQS «пакетное окно»:

https://aws.amazon.com/about-aws/whats-new/2020/11/aws-lambda-now-supports-batch-windows-of-up-to-5-minutes-for-functions/

Используя это, вы можете разрешить очереди SQS собирать сообщения в течение 5 минут, прежде чем будет вызвана функция Lambda.

Комментарии:

1. Спасибо за обновленный ответ, прошло много времени с тех пор, как я это сделал, и в настоящее время не работает над этим проектом. Я проверю это при необходимости в будущем

2. MaximumBatchingWindowInSeconds говорит: «Максимальное количество времени в секундах, которое Лямбда тратит на сбор записей перед вызовом функции».. Свойство используется для ожидания достижения размера пакета. Если вам нужно подождать X минут для выполнения каждого сообщения в очереди, это решение не сработает, например, если размер пакета равен 10 и накоплено 9 сообщений, когда придет следующее сообщение, выполнение будет немедленным, не дожидаясь необходимой задержки в x минут.

Ответ №3:

Секунды задержки: это задерживает вызов получения сообщения всякий раз, когда вы опрашиваете очередь. Но всякий раз, когда вы помещаете это сообщение в очередь, сообщение немедленно вставляется.

Если вы хотите, чтобы ваша лямбда выполнялась через определенный интервал после запуска триггера, установите режим ожидания (n) перед началом выполнения и увеличьте время ожидания лямбды, если требуется. На данный момент нет прямого способа отложить запуск, ваш лямбда-код будет запущен, как только сообщение окажется в очереди.

Комментарии:

1. Это не оптимальное решение, потому что стоимость lambda привязана ко времени выполнения

2. @Nikaidoh абсолютно правильно. Это добавит накладные расходы, основанные на объеме памяти, используемой за этот конкретный промежуток времени.