Long Polling in AWS SQS causes application to hang

Viewed 958

I have an application written in C# that long polls a SQS queue with a ReceiveWaitTime of 20 seconds, and the max number of messages read is one.

This application uses AWSSDK.SQS (3.3.3.62).

I am running into a bit of an issue where the polling seems to just hang indefinitely and does not stop polling until the application is restarted (when the application is restarted, we re-create the Message Queue Monitor and start polling from there).

Here is the bit of code that does the polling:

private async Task ReceiveInternalAsync(Func<IMessageReceipt, Task> onMessageReceived,
            bool processAsynchronously, TimeSpan? maximumWait = null, CancellationToken? cancellationToken = null, int maxNumberOfMessages = 1)
{
    var request = new ReceiveMessageRequest();
    var totalWait = maximumWait ?? TimeSpan.MaxValue;
    request.QueueUrl = Address;
    request.WaitTimeSeconds = GetSqsWaitTimeSeconds(totalWait, cancellationToken.HasValue);
    request.MaxNumberOfMessages = maxNumberOfMessages;

    var stopwatch = Stopwatch.StartNew();

    Amazon.SQS.Model.Message[] sqsMessages;

    while (true)
    {
        var stopwatch2 = Stopwatch.StartNew();

        var response = await _sqsClient.ReceiveMessageAsync(request).ConfigureAwait(false);

        stopwatch2.Stop();

        sqsMessages = response.Messages.Where(i => i != null).ToArray();

        _logger.LogDebug($"{request.QueueUrl} {sqsMessages.Length} messages received after {stopwatch2.ElapsedMilliseconds} ms");
        ...
    }
}

Where the parameters being sent to this method are:

  • onMessagedReceived = a delegate to handle the received message
  • processAsynchronously = true
  • maximumWait = 20 seconds (new TimeSpan(0,0,20))
  • cancellationToken = null
  • maxNumberOfMessages = 1

I have omitted the rest of the while loop, as I don't believe it's indefinitely looping in there, but I am more than welcome to share the rest of it, if we think it can be the crux of the issue.

The reason why I believe it's the sdk that is hanging is because I don't see the debug message:

{request.QueueUrl} {sqsMessages.Length} messages received after {stopwatch2.ElapsedMilliseconds} ms

Appear, and I know it has hit this method because the caller has a log that states that it has called this method (let me know if I should share the caller's code as well).

I looked up similar issues online and I found this:

which seems similar to what I have.

The issue is that this seems to only happen on production whereas locally I cannot replicate to the full extent where it never polls again.

What I have done locally is:

Scenario 1: disconnect completely from the internet

  1. Long Poll queue that has no messages in it
  2. Disconnect from the Internet before 20 seconds are up
  3. About 1 minute and 40 seconds, the AWS SDK will not throw an error but continue on as if there were empty messages in the queue
  4. About 2 minutes in or 2 minutes and 30 seconds in I get a DNS name resolution error

Scenario 2: disconnect from the internet for 1 minute and 40 seconds and reconnect

Based on my analysis from the above scenario, I wondered then what would happen if I were to reconnect after step 3) in scenario 1.

I found that the AWS SDK will wait for 20 seconds to retrieve any messages from the queue.

Theory as to what's happening

I suppose we can have indefinite polling if the client's network keeps going in and out of a connection, such that they are not disconnected for a total of 1 minute and 40 seconds but keep disconnecting and reconnecting before the 20 seconds are up?

Has anyone encountered this issue before? My temporary solution is to send a cancellationToken with a client-side timeout specified. Just wondering if there is any other reasons for the indefinite polling?

Thank you very much for the help!

0 Answers
Related