SQS Performance

Hi.

I have a windows service which I’m using to both publish and consume an Amazon SQS message. I am seeing very poor performance (approximately 10 seconds before the message arrives).

Any thoughts other than Amazon performance you could suggest me to look into ?

For the client part I’m using the following code:

            var awsAccessKey = ConfigurationManager.AppSettings.Get("AwsAccessKey");
            var awsSecretKey = ConfigurationManager.AppSettings.Get("AwsSecretKey");
            var awsRegionEndpoint = ConfigurationManager.AppSettings.Get("AwsRegionEndpoint");
            var region = RegionEndpoint.GetBySystemName(awsRegionEndpoint);
            var queueUrl = ConfigurationManager.AppSettings.Get("QueueUrl");

            var mqServer = new SqsMqServer(
                awsAccessKey,
                awsSecretKey,
                region)
            { DisableBuffering = true };// Trade-off latency vs efficiency

            var mqClient = mqServer.ConnectionFactory.GetClient();
            var request = new Amazon.SQS.Model.SendMessageRequest();

            var json = JsonSerializer.SerializeToString<T>((T)ob1);

            mqClient.SendMessage(queueUrl, json);

For the Server part I’m using

  public override void Configure(Funq.Container container) {

        var queueProvider = ConfigurationManager.AppSettings.Get("QueueProvider");
        var awsAccessKey = ConfigurationManager.AppSettings.Get("AwsAccessKey");
        var awsSecretKey = ConfigurationManager.AppSettings.Get("AwsSecretKey");
        var awsRegionEndpoint = ConfigurationManager.AppSettings.Get("AwsRegionEndpoint");
        var region = RegionEndpoint.GetBySystemName(awsRegionEndpoint);
        var queueUrl = ConfigurationManager.AppSettings.Get("QueueUrl");

        container.Register<IMessageService>(c => new SqsMqServer(
                awsAccessKey,
                awsSecretKey,
                region)
            { DisableBuffering = true });

            var mqServer = container.Resolve<IMessageService>();

            mqServer.RegisterHandler<InboundMessage>(ExecuteMessage);

            mqServer.Start();
        }

Did you make changes for Delivery Delay when you created Amazon queue? This can affect overall performance of the Amazon queue.

Thanks for the reply, no the delivery delay is zero.

Do you have such long messages delivering in all regions or only for specific one? What is the size of the message and how do you measure delivering time (do you send and receive message on the same instance? If not and you are using logs to get the time difference are these times are same on both machines?)

I have only tested on the one region so far US-EAST-1

The message is very small, approximately a 200 byte payload

Delivering time I’m testing using a pack sender, as the process is:

UDP Message Send -> UDP Msg Receive -> Publish Message -> Consume Message, Ack Message. I intend to shift the ack, but I’m still concerned about the lack of throughput.

I am also debugging the publish and consume points in the code, and can confirm a delay of greater than 10 seconds normally.

I should mention that I am testing this off of Amazon, so I am expecting some latency, but 10 seconds appears way too much to be geographic latency driven.

Also I have used the following:

mqServer1.RegisterHandler(ExecuteMessage, noOfThreads: 4);

in a hope to have 4 worker threads receiving these messages. If I send 3 messages I would expect a delay of 10 seconds then for 3 acks to arrive, however, I’m seeing something that appears more like a serial operation send, send, send, 10 second, ack, 10 second, ack, 10 second, ack

An update on this, delay appeared to be mostly to do with the constructor authenticating Amazon side. I created a singleton and performance improve significantly (back to being what I would expect)

Hi Matt, can you show some of the code you changed to resolve this issue please?

Sorry this took so long to respond, here is a single class I created

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Security.Principal;
using System.Text.RegularExpressions;
using System.Configuration;
using ServiceStack.Redis;
using ServiceStack.Aws.Sqs;
using Amazon;
using Amazon.SQS;
using ServiceStack.Text;
using ServiceStack;

namespace QueueManagement
{

public sealed class QueueManager
{
    private static readonly QueueManager instance = new QueueManager();
    private SqsMqServer _mqServer;
    private string _awsAccessKey;
    private string _awsSecretKey;
    private RegionEndpoint _region;
    private string _queueUrl;
    private string _queueUrl_Outbound;

    static QueueManager()
    {
    }

    private QueueManager()
    {
        var queueProvider = ConfigurationManager.AppSettings.Get("QueueProvider");

        if (queueProvider == "SQS")
        {
            ErrorHandler.Log(System.Diagnostics.TraceLevel.Verbose, "Queue Provider: SQS");
            _awsAccessKey = ConfigurationManager.AppSettings.Get("AwsAccessKey");
            _awsSecretKey = ConfigurationManager.AppSettings.Get("AwsSecretKey");
            var awsRegionEndpoint = ConfigurationManager.AppSettings.Get("AwsRegionEndpoint");
            _region = RegionEndpoint.GetBySystemName(awsRegionEndpoint);
            _queueUrl = ConfigurationManager.AppSettings.Get("QueueUrl");
            _queueUrl_Outbound = ConfigurationManager.AppSettings.Get("QueueUrl_Outbound");
            ErrorHandler.Log(System.Diagnostics.TraceLevel.Verbose, "Access Key: " + _awsAccessKey +
                ", Region Endpoint: " + awsRegionEndpoint +
                ", queueUrl: " + _queueUrl);

            ErrorHandler.Log(System.Diagnostics.TraceLevel.Verbose, "Creating MQServer");
            _mqServer = new SqsMqServer(
                _awsAccessKey,
                _awsSecretKey,
                _region)
            { DisableBuffering = true };// Trade-off latency vs efficiency
            ErrorHandler.Log(System.Diagnostics.TraceLevel.Verbose, "MQServer: " + _mqServer.ToString());

        }
    }

    public static string ReponseToString(Amazon.SQS.Model.SendMessageResponse response)
    {
        if (response != null)
        {
            string str = "";
            if (response.ResponseMetadata != null) { str = str + "Meta: " + response.ResponseMetadata.ToString(); };
            if (response.HttpStatusCode != null) { str = str + ", Response: " + response.HttpStatusCode.ToString(); };
            str = str + ", MessageId: " + response.MessageId;
            return str;
        }
        else
        {
            return "";
        }
    }

    public static QueueManager Instance
    {
        get
        {
            return instance;
        }
    }

    public IAmazonSQS GetClient()
    {
        return _mqServer.ConnectionFactory.GetClient();
    }

    public static void EnqueueMessage<T>(object ob1)
    {
        // this can be improved
        string qURL = "";
        Type typeParameterType = typeof(T);
        if (typeParameterType.Name == "InboundMessage")
        {
            qURL = QueueManager.Instance._queueUrl;
        } else if (typeParameterType.Name == "OutboundMessage")
        {
            qURL = QueueManager.Instance._queueUrl_Outbound;
        }

        using (var mqClient = QueueManager.Instance.GetClient())
        {
            var request = new Amazon.SQS.Model.SendMessageRequest();

            var json = JsonSerializer.SerializeToString<T>((T)ob1);
            ErrorHandler.Log(System.Diagnostics.TraceLevel.Verbose, "JSON: " + json);

            var response = mqClient.SendMessage(qURL, json);
            ErrorHandler.Log(System.Diagnostics.TraceLevel.Verbose, "Queued Message: " + ReponseToString(response));
        }
    }
}

}

1 Like