SQS maxNumberOfMessages

11

Utilizando una aplicación cliente Java, estoy consultando una cola SQS para mensajes. La cola tiene 12,000 mensajes como configuración para la prueba. Estoy usando openJDK con aws-java-sdk latest (software.amazon.awssdk 2.10.62) pom.xml se muestra más abajo.

El problema que estoy viendo es que, a pesar de establecer maxNumberOfMessages (10) , solo recibo 3. Entiendo que es un máximo, no una garantía de la cantidad de mensajes, sin embargo, no hay vacilación en la cantidad de mensajes devueltos. Siempre es 3.

Documentación de AWS: MaxNumberOfMessages El número máximo de mensajes a devolver. Amazon SQS nunca devuelve más mensajes que este valor (sin embargo, podrían devolverse menos mensajes). Valores válidos: de 1 a 10. Valor predeterminado: 1. Tipo: Entero Requerido: No

Consumir mensajes usando sondeo corto

Cuando consume mensajes de una cola utilizando sondeos cortos, Amazon SQS muestrea un subconjunto de sus servidores (en función de una distribución aleatoria ponderada) y devuelve mensajes solo de esos servidores. Por lo tanto, una solicitud de ReceiveMessage en particular podría no devolver todos sus mensajes. Sin embargo, si tiene menos de 1,000 mensajes en su cola, una solicitud posterior devolverá sus mensajes. Si sigue consumiendo de sus colas, Amazon SQS muestrea todos sus servidores y recibe todos sus mensajes.

Por lo tanto, hemos probado dos clientes en Java utilizando tanto el aws sdk anterior como el nuevo con los mismos resultados. Siempre solo 3 mensajes de vuelta.

Curiosamente, si en lugar de ejecutar la aplicación externamente (en mi poderoso escritorio) la ejecutas como AWS Lambda, obtienes 10 mensajes. Esta prueba lambda fue realizada usando JavaScript por un colega.

Entonces, la pregunta sigue siendo por qué solo recibimos 3 mensajes por solicitud y aparentemente dentro de lambda puede obtener 10.

Dado que hay un costo por solicitud, la distribución aleatoria ponderada se basa en el beneficio de Amazon =))

Método de prueba 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
fuente
Solo una idea, pero ¿ha verificado la configuración de la cola en AWS? ¿Tal vez se configuró con una propiedad maxNumberOfMessages que podría tener prioridad sobre la que configuró en el cliente java? Dado que funciona en el javascript lambda, esto sería extraño, pero vale la pena
intentarlo

Respuestas:

9

Dado que hay un costo por solicitud, la distribución aleatoria ponderada se basa en el beneficio de Amazon =))

Está claro que su objetivo aquí es reducir los costos, ya sea enviando menos solicitudes a SQS o forzando a SQS a entregar la cantidad máxima de mensajes disponibles.

Como ha indicado en su pregunta, SQS no tiene la obligación de entregar la cantidad máxima de mensajes disponibles. Sin embargo, hay algo sobre lo que me gustaría informarle, suponiendo que aún no lo sepa.


Sondeo largo

La Guía para desarrolladores del Servicio de cola simple de Amazon establece:

El proceso de consumir mensajes de una cola depende de si usa sondeo corto o largo. De manera predeterminada, Amazon SQS utiliza una encuesta breve , que consulta solo un subconjunto de sus servidores (en función de una distribución aleatoria ponderada) para determinar si hay mensajes disponibles para una respuesta. Puede usar encuestas largas para reducir sus costos y permitir a sus consumidores recibir mensajes tan pronto como lleguen a la cola.

Los mensajes que envió a SQS pueden haberse almacenado en servidores separados. Como se indica en la documentación, solo se puede consultar un subconjunto de servidores si su cola está configurada para utilizar sondeos cortos . Supongo que tuvo mala suerte al invocar receiveMessagey solo 3fue devuelto cada vez.

Si observamos los beneficios de las encuestas largas en la misma página de documentación, dice:

Las encuestas largas ofrecen los siguientes beneficios:

  • Elimine las respuestas vacías permitiendo que Amazon SQS espere hasta que un mensaje esté disponible en una cola antes de enviar una respuesta. A menos que se agote el tiempo de espera de la conexión, la respuesta a la solicitud de Recibir mensaje contiene al menos uno de los mensajes disponibles, hasta el número máximo de mensajes especificado en la acción Recibir mensaje.

  • Elimine las respuestas vacías falsas consultando todos los servidores de Amazon SQS, en lugar de un subconjunto de ellos.

La segunda viñeta es muy importante aquí. Aunque no esté viendo respuestas vacías, puede haber más mensajes almacenados en servidores que no se están consultando. Si habilita el sondeo largo, es de esperar que vea un aumento en la cantidad de mensajes devueltos, suponiendo que haya más de 3 servidores en total.

Por lo tanto, mi sugerencia es habilitar un sondeo largo en su cola. Para hacerlo, consulte la página Configuración de sondeo largo .


Como DevilCode mencionó en su comentario a continuación, pudo resolver su problema mediante el uso de una cola FIFO en lugar de una cola estándar, y al permitir un sondeo largo en él.

Jacob G.
fuente
Hemos probado lo mismo con encuestas largas y obtuvimos el mismo resultado. Teníamos 12,000 mensajes en la cola y el sondeo establecido en 20 segundos. Todavía solo recibimos tres mensajes. Si recibimos tres mensajes con sondeo largo y corto, no hay razón para usar sondeo largo (excepto si la cola está vacía esperando mensajes). Lamentablemente, estamos tratando de equilibrar el costo y la velocidad. Desafortunadamente, solo tenemos hilos de lectura limitados que podemos usar (debido al hardware), por lo que la cantidad de mensajes que podemos desplegar por llamada es un factor limitante en la rapidez con la que podemos procesarlo.
DevilCode
@DevilCode No pude reproducir su problema de mi parte con el sondeo largo habilitado. ¿Es su cola una cola estándar o una cola FIFO? También es posible que desee abrir un ticket de soporte con AWS para ver si pueden realizar cambios en su extremo.
Jacob G.
Es una cola estándar. ¿Ejecutó su código localmente y estábamos usando Java?
DevilCode
@DevilCode Lo probé usando una cola FIFO. Y sí, estoy usando AWS Java SDK v2 para recibir mensajes de mi cola SQS. Mi código no se ejecuta dentro de una función AWS Lambda.
Jacob G.
1
OK Probamos la cola FIFO y obtenemos 10 mensajes donde, como en la cola estándar, obtenemos solo tres. Todo lo que puedo concluir ahora es que la documentación se refiere a la cola FIFO y no a la cola estándar.
DevilCode
0

Creo que esta es una pregunta similar. Como señaló Jacob, las encuestas largas parecen ser la solución al problema.

charbel k
fuente
0

Sondeo largo:

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