DavKa
DavKa

Reputation: 326

AWS SQS error handling

As everything fail one day or the other. Are there any recommendations/best practices on how to handle errors when publishing messages to Amazon SQS?

I am running the Amazon .NET SDK and send a couple of 1000 SQS messages a day. It hasnt come to my attention that publishing has failed but that could be that any problem hasent surfaced.

However, how should I handle an error in the following basic code (pretty much a straight forward usage example from the SDK documentation):

public static string sendSqs(string data)
{
  IAmazonSQS sqs = AWSClientFactory.CreateAmazonSQSClient(RegionEndpoint.EUWest1);
  SendMessageRequest sendMessageRequest = new SendMessageRequest();
  CreateQueueRequest sqsRequest = new CreateQueueRequest();
  sqsRequest.QueueName = "mySqsQueue";
  CreateQueueResponse createQueueResponse = sqs.CreateQueue(sqsRequest);
  sendMessageRequest.QueueUrl = createQueueResponse.QueueUrl;
  sendMessageRequest.MessageBody = data;
  SendMessageResponse sendMessageresponse = sqs.SendMessage(sendMessageRequest);
  return sendMessageresponse.MessageId;
}

Upvotes: 0

Views: 11239

Answers (2)

Adrian Hofman
Adrian Hofman

Reputation: 1451

You shouldn't need to do much of your own error handling at all; the AWS SDK for .NET handles retries for transient failures under the hood.

It will automatically retry any request that fails if:

  • your access to the AWS service is being throttled
  • the request times out
  • the HTTP connection fails

It uses an exponential backoff strategy for multiple retries. On the first failure, it sleeps for 400 ms, then tries again. If that attempt fails, it sleeps for 1600 ms before trying again. If that fails, it sleeps for 6400 ms, and so on, to a maximum of 30 seconds.

When the configured maximum number of retries is reached, the SDK will throw. You can configure the maximum number of retries like this:

var sqsClient = AWSClientFactory.CreateAmazonSQSClient( 
            new AmazonSQSConfig
            {
                MaxErrorRetry = 4 // the default is 4.
            });

If the API call ends up throwing, it means that something is really wrong, like SQS has gone down in your region, or your request is invalid.

Source: The AWS SDK for .NET Source Code on GitHub.

Upvotes: 2

alph486
alph486

Reputation: 1249

First (kinda unrelated) I would recommend separating the client from the send message:

public class QueueStuff{
private static IAmazonSQS SQS; 

//Get only one of these
public QueueStuff(){
   SQS = AWSClientFactory.CreateAmazonSQSClient(RegionEndpoint.EUWest1);
}
//...use SQS elsewhere...

Finally to answer your question: check the Common Errors and SendMessage (in your case) pages and catch relevant exceptions. What you do will depend on your app and how it should handle losing messages. An example might be:

public static string sendSqs(string data)
{
  SendMessageRequest sendMessageRequest = new SendMessageRequest();
  CreateQueueRequest sqsRequest = new CreateQueueRequest();
  sqsRequest.QueueName = "mySqsQueue";
  CreateQueueResponse createQueueResponse = sqs.CreateQueue(sqsRequest);
  sendMessageRequest.QueueUrl = createQueueResponse.QueueUrl;
  sendMessageRequest.MessageBody = data;
  try{
      SendMessageResponse sendMessageresponse = SQS.SendMessage(sendMessageRequest);
  catch(InvalidMessageContents ex){ //Catch or bubble the exception up.
    //I can't do anything about this so toss the message...
    LOGGER.log("Invalid data in request: "+data, ex);
    return null;
  } catch(Throttling ex){ //I can do something about this!
    //Exponential backoff...
  }
  return sendMessageresponse.MessageId;
}

Exceptions like Throttling or ServiceUnavailable are ones commonly overlooked but can be handled properly. Its commonly recommended that for things like these you implement an Exponential Backoff. When you're throttled you backoff until the service is available again. An example of implementation and usage in Java: https://gist.github.com/alph486/f123ea139e6ea56e696f .

Upvotes: 2

Related Questions