SQS maxNumberOfMessages

11

Mit einer Java-Client-Anwendung frage ich eine SQS-Warteschlange nach Nachrichten ab. Die Warteschlange enthält 12.000 Nachrichten als Testeinrichtung. Ich verwende openJDK mit der neuesten Version von aws-java-sdk (software.amazon.awssdk 2.10.62). Pom.xml wird weiter unten angezeigt.

Das Problem, das ich sehe, ist, dass ich trotz der Einstellung von maxNumberOfMessages (10) immer nur 3 bekomme. Ich verstehe, dass dies maximal keine Garantie für die Anzahl der Nachrichten ist, aber es gibt keinen Schwank in der Anzahl der zurückgegebenen Nachrichten. Es ist immer 3.

AWS-Dokumentation: MaxNumberOfMessages Die maximale Anzahl der zurückzugebenden Nachrichten. Amazon SQS gibt niemals mehr Nachrichten als diesen Wert zurück (es werden jedoch möglicherweise weniger Nachrichten zurückgegeben). Gültige Werte: 1 bis 10. Standard: 1. Typ: Ganzzahl Erforderlich: Nein

Nachrichten mit kurzen Abfragen verbrauchen

Wenn Sie Nachrichten aus einer Warteschlange mithilfe einer kurzen Abfrage verwenden, tastet Amazon SQS eine Teilmenge seiner Server ab (basierend auf einer gewichteten Zufallsverteilung) und gibt nur Nachrichten von diesen Servern zurück. Daher gibt eine bestimmte ReceiveMessage-Anforderung möglicherweise nicht alle Ihre Nachrichten zurück. Wenn sich jedoch weniger als 1.000 Nachrichten in Ihrer Warteschlange befinden, werden Ihre Nachrichten durch eine nachfolgende Anforderung zurückgegeben. Wenn Sie weiterhin in Ihren Warteschlangen arbeiten, testet Amazon SQS alle seine Server und Sie erhalten alle Ihre Nachrichten.

Daher haben wir zwei Clients in Java mit dem älteren aws sdk und dem neueren mit den gleichen Ergebnissen getestet. Immer nur 3 Nachrichten zurück.

Interessanterweise erhalten Sie 10 Nachrichten, wenn Sie die Anwendung nicht extern (auf meinem mächtigen Desktop) als AWS Lambda ausführen. Dieser Lambda-Test wurde von einem Kollegen mit JavaScript durchgeführt.

Es bleibt also die Frage, warum wir immer nur 3 Nachrichten pro Anfrage erhalten und scheinbar innerhalb von Lambda 10.

Da es Kosten pro Anfrage gibt, ist die gewichtete Zufallsverteilung basierend auf Amazon Profit =))

SQS-Testmethode:

public void SQStart()
{
    AwsBasicCredentials awsCreds = AwsBasicCredentials.create("accessKeyID", "secretKeyID");
    AwsCredentialsProvider creds = StaticCredentialsProvider.create(awsCreds);
    SqsClient sqs = SqsClient.builder().credentialsProvider(creds).region(Region.EU_WEST_1).build();
    GetQueueUrlRequest getQueueRequest = GetQueueUrlRequest.builder()
            .queueName(QUEUE_NAME)
            .build();
    String queueUrl = sqs.getQueueUrl(getQueueRequest).queueUrl();

    for (int x =1; x < 100; x++) {
        ReceiveMessageRequest receiveMessageRequest = ReceiveMessageRequest.builder()
                .queueUrl(queueUrl)
                .maxNumberOfMessages(10)
                .build();


        List<Message> messages = sqs.receiveMessage(receiveMessageRequest).messages();
        if (messages.size() > 3 ) {
            System.out.println("YEY More than 3 Messages: "+ messages.size());
        }
    }
}

POM.XML:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>groupId</groupId>
    <artifactId>SQSTest</artifactId>
    <version>1.0-SNAPSHOT</version>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>


    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>software.amazon.awssdk</groupId>
                <artifactId>bom</artifactId>
                <version>2.10.62</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>

            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>software.amazon.awssdk</groupId>
            <artifactId>sqs</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.9</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpcore</artifactId>
            <version>4.4.10</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.11.720</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>1.6.1</version>
        </dependency>
    </dependencies>
</project>
DevilCode
quelle
Nur ein Gedanke, aber haben Sie die Konfiguration der Warteschlange selbst in AWS überprüft? Vielleicht wurde es mit einer maxNumberOfMessages-Eigenschaft eingerichtet, die möglicherweise Vorrang vor der im Java-Client festgelegten hat? Da es im Javascript Lambda funktioniert, wäre dies seltsam, aber immer noch einen
Versuch

Antworten:

9

Da es Kosten pro Anfrage gibt, ist die gewichtete Zufallsverteilung basierend auf Amazon Profit =))

Es ist klar, dass Ihr Ziel hier darin besteht, die Kosten zu senken, indem Sie weniger Anforderungen an SQS senden oder SQS zwingen, die maximal verfügbare Anzahl von Nachrichten zuzustellen.

Wie Sie in Ihrer Frage angegeben haben, ist SQS nicht verpflichtet, die maximal verfügbare Anzahl von Nachrichten zuzustellen. Es gibt jedoch etwas, über das ich Sie informieren möchte, vorausgesetzt, Sie wissen es noch nicht.


Lange Umfrage

Im Entwicklerhandbuch des Simple Queue Service von Amazon heißt es:

Der Vorgang des Verzehrs von Nachrichten aus einer Warteschlange hängt davon ab, ob Sie kurze oder lange Abfragen verwenden. Standardmäßig verwendet Amazon SQS eine kurze Abfrage , bei der nur eine Teilmenge seiner Server (basierend auf einer gewichteten Zufallsverteilung) abgefragt wird, um festzustellen, ob Nachrichten für eine Antwort verfügbar sind. Sie können lange Abfragen verwenden , um Ihre Kosten zu senken und Ihren Verbrauchern zu ermöglichen, Nachrichten zu empfangen, sobald sie in der Warteschlange ankommen.

Die Nachrichten, die Sie an SQS gesendet haben, wurden möglicherweise alle auf separaten Servern gespeichert. Wie in der Dokumentation angegeben, kann nur eine Teilmenge von Servern abgefragt werden, wenn Ihre Warteschlange auf kurze Abfragen eingestellt ist . Ich vermute, dass Sie beim Aufrufen Pech hatten receiveMessageund nur 3jedes Mal zurückgegeben wurden.

Wenn wir uns die Vorteile einer langen Abfrage auf derselben Dokumentationsseite ansehen , heißt es:

Langes Polling bietet folgende Vorteile:

  • Beseitigen Sie leere Antworten, indem Sie Amazon SQS warten lassen, bis eine Nachricht in einer Warteschlange verfügbar ist, bevor Sie eine Antwort senden. Sofern die Verbindung nicht abläuft, enthält die Antwort auf die ReceiveMessage-Anforderung mindestens eine der verfügbaren Nachrichten, bis zu der in der ReceiveMessage-Aktion angegebenen maximalen Anzahl von Nachrichten.

  • Beseitigen Sie falsche leere Antworten, indem Sie alle Amazon SQS-Server und nicht nur eine Teilmenge davon abfragen.

Die zweite Kugel ist hier sehr wichtig. Auch wenn Sie keine leeren Antworten sehen, sind möglicherweise mehr Nachrichten auf Servern gespeichert, die nicht abgefragt werden. Wenn Sie lange Abfragen aktivieren, sollte hoffentlich die Anzahl der zurückgegebenen Nachrichten zunehmen, vorausgesetzt, es gibt insgesamt mehr als 3 Server.

Daher ist mein Vorschlag, lange Abfragen in Ihrer Warteschlange zu aktivieren. Informationen hierzu finden Sie auf der Seite Einrichten langer Abfragen .


Wie DevilCode in seinem Kommentar unten erwähnte , konnte er sein Problem beheben, indem er eine FIFO-Warteschlange anstelle einer Standardwarteschlange verwendete und eine lange Abfrage darauf ermöglichte.

Jacob G.
quelle
Wir haben das gleiche mit langen Umfragen getestet und das gleiche Ergebnis erzielt. Wir hatten 12.000 Nachrichten in der Warteschlange und die Abfrage auf 20 Sekunden eingestellt. Wir bekommen immer noch nur drei Nachrichten. Wenn wir drei Nachrichten mit langen und kurzen Abfragen erhalten, gibt es keinen Grund, lange Abfragen zu verwenden (außer wenn die Warteschlange leer ist und auf Nachrichten wartet). Leider versuchen wir Kosten und Geschwindigkeit in Einklang zu bringen. Leider haben wir nur begrenzte Lesethreads, die wir verwenden können (aufgrund der Hardware), sodass die Anzahl der Nachrichten, die wir pro Anruf abrufen können, ein begrenzender Faktor dafür ist, wie schnell wir sie verarbeiten können.
DevilCode
@ DevilCode Ich konnte Ihr Problem bei aktivierter langer Abfrage nicht reproduzieren. Ist Ihre Warteschlange eine Standardwarteschlange oder eine FIFO-Warteschlange? Möglicherweise möchten Sie auch ein Support-Ticket mit AWS öffnen, um zu prüfen, ob sie am Ende Änderungen vornehmen können.
Jacob G.
Es ist eine Standardwarteschlange. Haben Sie Ihren Code lokal ausgeführt und haben wir Java verwendet?
DevilCode
@ DevilCode Ich habe es mit einer FIFO-Warteschlange getestet. Und ja, ich verwende das AWS Java SDK v2, um Nachrichten aus meiner SQS-Warteschlange zu empfangen. Mein Code wird nicht in einer AWS Lambda-Funktion ausgeführt.
Jacob G.
1
OK Testete die FIFO-Warteschlange und wir erhalten 10 Nachrichten, wobei wie in der Standardwarteschlange nur drei angezeigt werden. Alles, was ich jetzt schließen kann, ist, dass sich die Dokumentation auf die FIFO-Warteschlange und nicht auf die Standardwarteschlange bezieht.
DevilCode
0

Ich denke, dies ist eine ähnliche Frage. Wie Jacob betonte, scheinen lange Umfragen die Lösung für das Problem zu sein.

charbel k
quelle
0

Lange Umfrage:

        ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl)
              .withWaitTimeSeconds(10)     // long poll: wait 10 seconds, max is 20 seconds
              .withMaxNumberOfMessages(10);
Justin
quelle