Безсерверный потребитель SQS пропускает сообщения - PullRequest
0 голосов
/ 27 декабря 2018

Я использую Serverless Framework для получения сообщений из SQS.Некоторые сообщения, отправленные в очередь, не расходуются.Они переходят прямо в состояние SQS в полете, а оттуда в мою очередь недоставленных писем.Когда я просматриваю свой журнал потребителя, я вижу, что он потребляет и успешно обработал 9/10 сообщений.Один всегда не потребляется и попадает в очередь мертвых писем.Я устанавливаю reservedConcurrency на 1, чтобы одновременно мог работать только один потребитель.Функция потребителя timeout установлена ​​на 30 секунд.Это код потребителя:

module.exports.mySQSConsumer = async (event, context) => {
  context.callbackWaitsForEmptyEventLoop = false;

  console.log(event.Records);

  await new Promise((res, rej) => {
    setTimeout(() => {
      res();
    }, 100);
  });

  console.log('DONE');

  return true;
}

Ниже приведена конфигурация функции потребителя:

functions:
  mySQSConsumer:
    handler: handler.mySQSConsumer
    timeout: 30 # seconds
    reservedConcurrency: 1
    events:
      - sqs:
          arn: arn:aws:sqs:us-east-1:xyz:my-test-queue
          batchSize: 1
          enabled: true

Если я удалю функцию await, она обработает все сообщения.Если я увеличу время ожидания до 200 мс, еще больше сообщений перейдет прямо к статусу в полете и оттуда в очередь недоставленных сообщений.Этот код очень прост.Есть идеи, почему он пропускает некоторые сообщения?Сообщения, которые не используются, даже не отображаются в журнале с использованием первого оператора console.log().Кажется, они полностью игнорируются.

1 Ответ

0 голосов
/ 29 декабря 2018

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

Проблема заключалась в том, что Default Visibility Timeout было установлено на 30 секунд, а Reserved Concurrency установлено на 1. Когда очередь SQS быстро заполняетсяс тысячами записей AWS начинает отправлять сообщения в функцию Lambda со скоростью, превышающей скорость, с которой один экземпляр функции может их обработать.AWS «предполагает», что он может просто раскрутить больше экземпляров Lambda, чтобы не отставать от противодавления.Однако ограничение параллелизма не позволяет ему раскручивать больше экземпляров - функция Lambda ограничена.В результате функция начинает возвращать сбой в серверную часть AWS для некоторых сообщений, что, следовательно, скрывает ошибочные сообщения в течение 30 секунд (настройка по умолчанию) и помещает их обратно в очередь после этого периода для повторной обработки.Поскольку для одного экземпляра необходимо обработать так много записей, через 30 секунд функция Lambda все еще занята и не может снова обработать эти сообщения.Таким образом, ситуация повторяется, и сообщения возвращаются в невидимость на 30 секунд.Это повторяется всего 3 раза.После третьей попытки сообщения отправляются в очередь недоставленных сообщений (таким образом мы настроили нашу очередь SQS).

Чтобы решить эту проблему, мы увеличили значение Default Visibility Timeout до 5 минут.Этого времени достаточно для того, чтобы лямбда-функция обрабатывала большинство сообщений в очереди, в то время как отказавшие ожидают в невидимости.Через 5 минут они возвращаются в очередь, и поскольку функция Lambda больше не занята, она будет обрабатывать большинство из них.Некоторым из них нужно дважды перейти в невидимость, прежде чем они будут успешно обработаны.

Таким образом, для решения этой проблемы нужно либо увеличить Default Invisibility Timeout, как мы, либо увеличить количество сбоев, необходимых для того, чтобы сообщение дошло до мертвых.Очередь писем.

Надеюсь, это кому-нибудь поможет.

...