SQS maxNumberOfMessages

11

À l'aide d'une application client Java, j'interroge une file d'attente SQS pour les messages. La file d'attente contient 12 000 messages comme configuration pour les tests. J'utilise openJDK avec aws-java-sdk dernier (software.amazon.awssdk 2.10.62) pom.xml est affiché plus bas.

Le problème que je vois est que, malgré la définition de maxNumberOfMessages (10), je n'en reçois que 3. Je comprends que ce n'est pas un maximum de garantie du nombre de messages, mais il n'y a pas de vacillement dans le nombre de messages renvoyés. C'est toujours 3.

Documentation AWS: MaxNumberOfMessages Nombre maximal de messages à renvoyer. Amazon SQS ne renvoie jamais plus de messages que cette valeur (cependant, moins de messages peuvent être renvoyés). Valeurs valides: 1 à 10. Valeur par défaut: 1. Type: entier requis: non

Consommation de messages à l'aide d'une interrogation courte

Lorsque vous consommez des messages d'une file d'attente à l'aide d'une interrogation courte, Amazon SQS échantillonne un sous-ensemble de ses serveurs (basé sur une distribution aléatoire pondérée) et renvoie des messages provenant uniquement de ces serveurs. Ainsi, une demande particulière de ReceiveMessage peut ne pas renvoyer tous vos messages. Cependant, si vous avez moins de 1 000 messages dans votre file d'attente, une demande ultérieure renverra vos messages. Si vous continuez à consommer à partir de vos files d'attente, Amazon SQS échantillonne tous ses serveurs et vous recevez tous vos messages.

Nous avons donc testé deux clients en java en utilisant à la fois l'ancien aws sdk et le plus récent avec les mêmes résultats. Toujours seulement 3 messages en retour.

Fait intéressant, si au lieu d'exécuter l'application en externe (sur mon puissant bureau), vous l'exécutez en tant que AWS Lambda, vous obtenez 10 messages. Ce test lambda a été effectué en utilisant JavaScript par un collègue.

La question reste donc de savoir pourquoi nous ne recevons que 3 messages par demande et apparemment, dans lambda, vous pouvez en obtenir 10.

Étant donné qu'il existe un coût par demande, la distribution aléatoire pondérée est basée sur le bénéfice d'Amazon =))

Méthode de test 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>
DevilCode
la source
Juste une pensée, mais avez-vous vérifié la configuration de la file d'attente elle-même sur AWS? Peut-être qu'il a été configuré avec une propriété maxNumberOfMessages qui pourrait avoir la priorité sur celle que vous avez définie dans le client java? Comme cela fonctionne dans le lambda javascript, ce serait bizarre, mais ça vaut quand même le coup :)
niekname

Réponses:

9

Étant donné qu'il existe un coût par demande, la distribution aléatoire pondérée est basée sur le bénéfice d'Amazon =))

Il est clair que votre objectif ici est de réduire les coûts, que ce soit en envoyant moins de demandes à SQS ou en forçant SQS à fournir le nombre maximal de messages disponibles.

Comme vous l'avez indiqué dans votre question, SQS n'a aucune obligation de fournir le nombre maximum de messages disponibles. Cependant, il y a quelque chose que j'aimerais vous informer, en supposant que vous n'en êtes pas déjà au courant.


Interrogation longue

Le Guide du développeur du service Simple Queue d'Amazon stipule:

Le processus de consommation des messages d'une file d'attente varie selon que vous utilisez l'interrogation courte ou longue. Par défaut, Amazon SQS utilise une interrogation courte , interrogeant uniquement un sous-ensemble de ses serveurs (basé sur une distribution aléatoire pondérée) pour déterminer si des messages sont disponibles pour une réponse. Vous pouvez utiliser l' interrogation longue pour réduire vos coûts tout en permettant à vos consommateurs de recevoir des messages dès leur arrivée dans la file d'attente.

Les messages que vous avez envoyés à SQS ont peut-être tous été stockés sur des serveurs distincts. Comme l'indique la documentation, seul un sous-ensemble de serveurs peut être interrogé si votre file d'attente est configurée pour utiliser l' interrogation courte . Je suppose que vous n'avez pas eu de chance lors de l'invocation receiveMessageet que vous avez 3été renvoyé à chaque fois.

Si nous examinons les avantages de l' interrogation longue sur la même page de documentation, il indique:

L'interrogation longue offre les avantages suivants:

  • Éliminez les réponses vides en permettant à Amazon SQS d'attendre qu'un message soit disponible dans une file d'attente avant d'envoyer une réponse. À moins que la connexion n'expire, la réponse à la demande ReceiveMessage contient au moins un des messages disponibles, jusqu'au nombre maximal de messages spécifié dans l'action ReceiveMessage.

  • Éliminez les fausses réponses vides en interrogeant tous les serveurs Amazon SQS plutôt qu'un sous-ensemble.

La deuxième puce est très importante ici. Même si vous ne voyez pas de réponses vides, il peut exister plus de messages stockés sur des serveurs qui ne sont pas interrogés. Si vous activez l'interrogation longue, vous devriez, espérons-le, voir une augmentation de la quantité de messages retournés, en supposant qu'il y a plus de 3 serveurs au total.

Par conséquent, ma suggestion est d'activer l'interrogation longue sur votre file d'attente. Pour ce faire, consultez la page Configuration de l'interrogation longue .


Comme DevilCode l'a mentionné dans son commentaire ci-dessous, il a pu résoudre son problème en utilisant une file d'attente FIFO au lieu d'une file d'attente standard et en activant une longue interrogation sur celle-ci.

Jacob G.
la source
Nous avons testé la même chose avec un long sondage et avons obtenu le même résultat. Nous avions 12 000 messages dans la file d'attente et l'interrogation était fixée à 20 secondes. Nous n'avons toujours que trois messages. Si nous obtenons trois messages avec une interrogation longue et courte, il n'y a aucune raison d'utiliser une interrogation longue (sauf si la file d'attente est vide en attente de messages). Malheureusement, nous essayons d'équilibrer les coûts et la vitesse. Malheureusement, nous n'avons que des threads de lecture limités que nous pouvons utiliser (en raison du matériel), de sorte que le nombre de messages que nous pouvons dérouler par appel est un facteur limitant la vitesse à laquelle nous pouvons le traiter.
DevilCode
@DevilCode Je n'ai pas pu reproduire votre problème de mon côté avec l'interrogation longue activée. Votre file d'attente est-elle une file d'attente standard ou une file d'attente FIFO? Vous pouvez également ouvrir un ticket de support avec AWS pour voir s'ils peuvent apporter des modifications de leur côté.
Jacob
Il s'agit d'une file d'attente standard. Avez-vous exécuté votre code localement et utilisiez-vous Java?
DevilCode
@DevilCode Je l'ai testé en utilisant une file d'attente FIFO. Et oui, j'utilise AWS Java SDK v2 pour recevoir des messages de ma file d'attente SQS. Mon code ne s'exécute pas dans une fonction AWS Lambda.
Jacob G.20
1
OK Testé la file d'attente FIFO et nous obtenons 10 messages alors que comme dans la file d'attente standard, nous n'en obtenons que trois. Tout ce que je peux conclure maintenant, c'est que la documentation se réfère à la file d'attente FIFO et non à la file d'attente standard.
DevilCode
0

Je pense que c'est un question.As similaire pointé par Jacob, à long polling semble être la solution à la question.

charbel k
la source
0

Interrogation longue:

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