MQ maxNumberOfMessages


11

Utilizzando un'applicazione client Java sto interrogando una coda SQS per i messaggi. La coda ha 12.000 messaggi come impostazione per il test. Sto usando openJDK con l'ultimo aws-java-sdk (software.amazon.awssdk 2.10.62) pom.xml è mostrato più in basso.

Il problema che sto vedendo è che nonostante l'impostazione di maxNumberOfMessages (10) ottengo sempre solo 3. Comprendo che è un massimo non una garanzia del numero di messaggi, tuttavia non vi è alcuna esitazione nel numero di messaggi restituiti. Sono sempre 3.

Documentazione AWS: MaxNumberOfMessages Il numero massimo di messaggi da restituire. Amazon SQS non restituisce mai più messaggi di questo valore (tuttavia, potrebbero essere restituiti meno messaggi). Valori validi: da 1 a 10. Predefinito: 1. Tipo: intero Richiesto: no

Consumo di messaggi utilizzando il polling breve

Quando consumi messaggi da una coda utilizzando il polling breve, Amazon SQS campiona un sottoinsieme dei suoi server (basato su una distribuzione casuale ponderata) e restituisce messaggi solo da quei server. Pertanto, una particolare richiesta RiceviMessage potrebbe non restituire tutti i tuoi messaggi. Tuttavia, se nella coda sono presenti meno di 1.000 messaggi, una richiesta successiva restituirà i messaggi. Se continui a consumare dalle tue code, Amazon SQS campiona tutti i suoi server e ricevi tutti i tuoi messaggi.

Quindi abbiamo testato due client in Java usando sia il vecchio aws sdk che il più recente con gli stessi risultati. Restano sempre solo 3 messaggi.

È interessante notare che invece di eseguire l'applicazione esternamente (sul mio potente desktop) la esegui come AWS Lambda ricevi 10 messaggi. Questo test lambda è stato eseguito utilizzando JavaScript da un collega.

Quindi la domanda rimane: perché riceviamo solo 3 messaggi per richiesta e apparentemente in Lambda puoi riceverne 10.

Dato che esiste un costo per richiesta è la distribuzione casuale ponderata basata sull'utile amazon =))

Metodo di prova SQS:

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>

Solo un pensiero, ma hai verificato la configurazione della coda stessa su AWS? Forse è stato impostato con una proprietà maxNumberOfMessages che potrebbe avere la priorità su quella impostata nel client Java? Dal momento che funziona nel lambda javascript, questo sarebbe strano, ma vale comunque la pena
provare

Risposte:


9

Dato che esiste un costo per richiesta è la distribuzione casuale ponderata basata sull'utile amazon =))

È chiaro che il tuo obiettivo qui è quello di ridurre i costi, sia inviando meno richieste a SQS, sia forzando SQS a consegnare la massima quantità di messaggi disponibili.

Come hai affermato nella tua domanda, SQS non ha l'obbligo di consegnare il numero massimo di messaggi disponibili. Tuttavia, c'è qualcosa di cui vorrei informarti, supponendo che tu non ne sia già a conoscenza.


Polling lungo

La Guida per gli sviluppatori del servizio di coda semplice di Amazon afferma:

Il processo di utilizzo dei messaggi da una coda dipende dall'uso del polling breve o lungo. Per impostazione predefinita, Amazon SQS utilizza il polling breve , interrogando solo un sottoinsieme dei suoi server (basato su una distribuzione casuale ponderata) per determinare se sono disponibili messaggi per una risposta. È possibile utilizzare il polling lungo per ridurre i costi e consentire ai consumatori di ricevere messaggi non appena arrivano in coda.

I messaggi inviati a SQS potrebbero essere stati tutti archiviati su server separati. Come indicato nella documentazione, solo un sottoinsieme di server può essere interrogato se la coda è impostata per utilizzare il polling breve . La mia ipotesi è che sei stato sfortunato quando hai invocato receiveMessagee solo 3ogni volta ti hanno restituito.

Se esaminiamo i vantaggi del polling lungo nella stessa pagina della documentazione, si afferma:

Il polling lungo offre i seguenti vantaggi:

  • Elimina le risposte vuote consentendo ad Amazon SQS di attendere che un messaggio sia disponibile in una coda prima di inviare una risposta. A meno che la connessione non scada, la risposta alla richiesta ReceiveMessage contiene almeno uno dei messaggi disponibili, fino al numero massimo di messaggi specificato nell'azione ReceiveMessage.

  • Elimina le risposte false vuote eseguendo una query su tutti i server Amazon SQS anziché su un sottoinsieme.

Il secondo proiettile è molto importante qui. Anche se non visualizzi risposte vuote, potrebbero esistere più messaggi archiviati su server a cui non viene eseguita la query. Se abiliti il ​​polling lungo, dovresti vedere un aumento della quantità di messaggi restituiti, supponendo che ci siano più di 3 server in totale.

Pertanto, il mio suggerimento è di abilitare il polling lungo sulla coda. Per fare ciò, vedere la pagina Impostazione polling lungo .


Come DevilCode ha menzionato nel suo commento di seguito, è stato in grado di risolvere il suo problema utilizzando una coda FIFO anziché una coda standard e abilitando il polling lungo su di esso.


Abbiamo testato lo stesso con sondaggi lunghi e ottenuto lo stesso risultato. Avevamo 12.000 messaggi in coda e il polling impostato su 20 secondi. Riceviamo ancora solo tre messaggi. Se riceviamo tre messaggi con polling lungo e con polling breve non c'è motivo di utilizzare il polling lungo (tranne se la coda è vuota in attesa di messaggi). Purtroppo stiamo cercando di bilanciare costi e velocità. Sfortunatamente abbiamo solo thread di lettura limitati che possiamo usare (a causa dell'hardware), quindi il numero di messaggi che possiamo estrarre per chiamata è un fattore limitante nella velocità con cui possiamo elaborarlo.
DevilCode

@DevilCode Non sono riuscito a riprodurre il problema da parte mia con il polling lungo abilitato. La tua coda è una coda standard o una coda FIFO? Potresti anche voler aprire un ticket di supporto con AWS per vedere se possono apportare modifiche al loro fine.
Jacob G.

È una coda standard. Hai eseguito il codice localmente e utilizzavamo Java?
DevilCode

@DevilCode L'ho provato usando una coda FIFO. E sì, sto usando AWS Java SDK v2 per ricevere messaggi dalla mia coda SQS. Il mio codice non funziona con una funzione Lambda AWS.
Jacob G.

1
OK Testato la coda FIFO e riceviamo 10 messaggi dove come nella coda standard ne otteniamo solo tre. Tutto ciò che posso concludere ora è che la documentazione si riferisce alla coda FIFO e non alla coda standard.
DevilCode

0

Penso che questa sia una domanda simile. Come sottolineato da Jacob, il lungo sondaggio sembra essere la soluzione al problema.


0

Polling lungo:

        ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl)
              .withWaitTimeSeconds(10)     // long poll: wait 10 seconds, max is 20 seconds
              .withMaxNumberOfMessages(10);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.