SQS maxNumberOfMessages

11

Usando um aplicativo cliente Java, estou consultando uma fila SQS para obter mensagens. A fila possui 12.000 mensagens como configuração para teste. Estou usando o openJDK com o aws-java-sdk mais recente (software.amazon.awssdk 2.10.62) pom.xml é mostrado mais abaixo.

O problema que estou vendo é que, apesar de definir maxNumberOfMessages (10) , apenas recebo 3. Entendo que é uma garantia máxima do número de mensagens, no entanto, não há oscilação no número de mensagens retornadas. É sempre 3.

Documentação da AWS: MaxNumberOfMessages O número máximo de mensagens a serem retornadas. O Amazon SQS nunca retorna mais mensagens que esse valor (no entanto, menos mensagens podem ser retornadas). Valores válidos: 1 a 10. Padrão: 1. Tipo: Inteiro Necessário: Não

Consumindo mensagens usando sondagens curtas

Quando você consome mensagens de uma fila usando sondagens curtas, o Amazon SQS mostra um subconjunto de seus servidores (com base em uma distribuição aleatória ponderada) e retorna mensagens apenas desses servidores. Portanto, uma solicitação ReceiveMessage específica pode não retornar todas as suas mensagens. No entanto, se você tiver menos de 1.000 mensagens em sua fila, uma solicitação subsequente retornará suas mensagens. Se você continuar consumindo em suas filas, o Amazon SQS fará uma amostra de todos os seus servidores e você receberá todas as suas mensagens.

Portanto, testamos dois clientes em java usando o aws sdk mais antigo e o mais novo com os mesmos resultados. Sempre apenas 3 mensagens de volta.

O interessante é que, em vez de executar o aplicativo externamente (na minha poderosa área de trabalho), você o executa como um AWS Lambda, recebe 10 mensagens. Este teste lambda foi realizado usando JavaScript por um colega.

Portanto, a questão permanece: por que só recebemos 3 mensagens por solicitação e, aparentemente, no lambda, você pode obter 10.

Dado que existe um custo por solicitação, a distribuição aleatória ponderada é baseada no lucro da amazon =))

Método de Teste 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
fonte
Apenas um pensamento, mas você verificou a configuração da própria fila na AWS? Talvez tenha sido configurado com uma propriedade maxNumberOfMessages que pode ter prioridade sobre a que você definiu no cliente java? Como ele funciona no lambda javascript, isso seria estranho, mas ainda vale a pena
tentar

Respostas:

9

Dado que existe um custo por solicitação, a distribuição aleatória ponderada é baseada no lucro da amazon =))

É claro que seu objetivo aqui é reduzir custos, enviando menos solicitações ao SQS ou forçando o SQS a entregar a quantidade máxima de mensagens disponíveis.

Como você afirmou em sua pergunta, o SQS não tem obrigação de entregar a quantidade máxima de mensagens disponíveis. No entanto, há algo que eu gostaria de informar, supondo que você ainda não esteja ciente disso.


Votação longa

O Guia do desenvolvedor do Serviço de fila simples da Amazon declara:

O processo de consumir mensagens de uma fila depende se você usa pesquisas curtas ou longas. Por padrão, o Amazon SQS usa pesquisa curta , consultando apenas um subconjunto de seus servidores (com base em uma distribuição aleatória ponderada) para determinar se há alguma mensagem disponível para uma resposta. Você pode usar a pesquisa longa para reduzir seus custos e permitir que seus consumidores recebam mensagens assim que chegarem na fila.

As mensagens enviadas para o SQS podem ter sido armazenadas em servidores separados. Como a documentação declara, apenas um subconjunto de servidores pode ser consultado se sua fila estiver configurada para usar uma pesquisa curta . Meu palpite é que você teve azar ao invocar receiveMessagee só 3foi devolvido todas as vezes.

Se olharmos para os benefícios da pesquisa longa na mesma página de documentação, ele afirma:

Pesquisas longas oferecem os seguintes benefícios:

  • Elimine respostas vazias, permitindo que o Amazon SQS aguarde até que uma mensagem esteja disponível em uma fila antes de enviar uma resposta. A menos que a conexão atinja o tempo limite, a resposta à solicitação ReceiveMessage contém pelo menos uma das mensagens disponíveis, até o número máximo de mensagens especificado na ação ReceiveMessage.

  • Elimine respostas falsas vazias consultando todos os servidores Amazon SQS, em vez de um subconjunto.

A segunda bala é muito importante aqui. Mesmo que você não esteja vendo respostas vazias, pode haver mais mensagens armazenadas em servidores que não estão sendo consultados. Se você ativar a sondagem longa, esperamos ver um aumento na quantidade de mensagens retornadas, supondo que haja mais de 3 servidores no total.

Portanto, minha sugestão é ativar a pesquisa longa na sua fila. Para fazer isso, consulte a página Configuração da pesquisa longa .


Como o DevilCode mencionou em seu comentário abaixo, ele foi capaz de resolver seu problema usando uma fila FIFO em vez de uma fila padrão e permitindo uma pesquisa longa.

Jacob G.
fonte
Testamos o mesmo com pesquisas longas e obtivemos o mesmo resultado. Tivemos 12.000 mensagens na fila e a pesquisa definida para 20 segundos. Ainda recebemos apenas três mensagens. Se recebermos três mensagens com sondagem longa e curta, não há razão para usar a sondagem longa (exceto se a fila estiver vazia aguardando mensagens). Infelizmente, estamos tentando equilibrar custo e velocidade. Infelizmente, temos apenas threads de leitura limitados que podemos usar (devido ao hardware), portanto o número de mensagens que podemos puxar por chamada é um fator limitante na rapidez com que podemos processá-lo.
DevilCode
@DevilCode Não consegui reproduzir seu problema do meu lado com a pesquisa longa ativada. Sua fila é uma fila padrão ou uma fila FIFO? Você também pode abrir um tíquete de suporte com a AWS para ver se eles podem fazer alterações.
Jacob G.
É uma fila padrão. Você executou seu código localmente e estávamos usando Java?
DevilCode
@DevilCode Eu testei usando uma fila FIFO. E sim, estou usando o AWS Java SDK v2 para receber mensagens da minha fila SQS. Meu código não está sendo executado em uma função do AWS Lambda.
Jacob G.
11
OK Testamos a fila FIFO e recebemos 10 mensagens, onde, na fila padrão, recebemos apenas três. Tudo o que posso concluir agora é que a documentação se refere à fila FIFO e não à fila padrão.
DevilCode
0

Acho que essa é uma pergunta semelhante. Como apontado por Jacob, pesquisas longas parecem ser a solução para o problema.

charbel k
fonte
0

Votação longa:

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