[java] SQS maxNumberOfMessages

Java 클라이언트 응용 프로그램을 사용하여 메시지에 대한 SQS 대기열을 쿼리하고 있습니다. 대기열에는 테스트를위한 설정으로 12,000 개의 메시지가 있습니다. 최신 aws-java-sdk (software.amazon.awssdk 2.10.62)와 함께 openJDK를 사용하고 있습니다. pom.xml이 더 아래에 표시되어 있습니다.

내가보고있는 문제는 maxNumberOfMessages (10) 설정에도 불구하고 3을 얻는 것입니다. 메시지 수를 보장하지 않는 최대 값이라는 것을 이해하지만 반환 된 메시지 수에는 흔들림이 없습니다. 항상 3입니다.

AWS 설명서 : MaxNumberOfMessages 반환 할 최대 메시지 수입니다. Amazon SQS는이 값보다 더 많은 메시지를 반환하지 않지만 더 적은 메시지가 반환 될 수 있습니다. 유효한 값 : 1 ~ 10. 기본값 : 1. 유형 : 정수 필수 : ​​아니요

짧은 폴링을 사용하여 메시지 소비

짧은 폴링을 사용하여 대기열에서 메시지를 사용하는 경우 Amazon SQS는 서버의 하위 집합 (가중 무작위 배포를 기반으로)을 샘플링하고 해당 서버에서만 메시지를 반환합니다. 따라서 특정 ReceiveMessage 요청이 모든 메시지를 리턴하지는 않습니다. 그러나 대기열에 메시지가 1,000 개 미만이면 후속 요청에서 메시지를 반환합니다. 대기열에서 계속 소비하면 Amazon SQS가 모든 서버를 샘플링하고 모든 메시지를 수신합니다.

그래서 우리는 이전 aws sdk와 새로운 결과를 사용하여 java에서 두 개의 클라이언트를 테스트했습니다. 항상 3 개의 메시지 만 회신합니다.

흥미롭게도 (내 강력한 데스크톱에서) 애플리케이션을 외부에서 실행하는 대신 AWS Lambda로 실행하면 10 개의 메시지가 표시됩니다. 이 람다 테스트는 동료가 JavaScript를 사용하여 수행했습니다.

그래서 우리는 왜 요청 당 3 개의 메시지 만 받고 람다 안에 10을 얻을 수 있는지 궁금합니다.

요청 당 비용이 주어지면 아마존 이익을 기반으로 한 가중 랜덤 분포 =))

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>



답변

요청 당 비용이 주어지면 아마존 이익을 기반으로 한 가중 랜덤 분포 =))

SQS에 더 적은 요청을 보내거나 SQS가 사용 가능한 최대 메시지를 전달하도록함으로써 비용을 절감하는 것이 목표라는 것이 분명합니다.

귀하의 질문에 언급했듯이 SQS는 사용 가능한 최대량의 메시지를 전달할 의무가 없습니다. 그러나 아직 알고 있지 않다고 가정하고 알려주는 것이 있습니다.


긴 폴링

개발자 가이드 아마존의 심플 큐 서비스 상태 :

큐에서 메시지를 소비하는 프로세스는 단문 폴링 또는 긴 폴링 사용 여부에 따라 다릅니다. 기본적으로 Amazon SQS는 짧은 폴링을 사용 하여 가중치가 적용된 임의 배포를 기반으로 서버의 하위 집합 만 쿼리하여 응답에 사용할 수있는 메시지가 있는지 확인합니다. 당신이 사용할 수있는 롱 폴링을 가 큐에 도착하자마자 메시지를받을 소비자를 허용하면서 비용을 줄일 수 있습니다.

SQS로 보낸 메시지는 모두 별도의 서버에 저장되었을 수 있습니다. 설명서에 나와 있듯이 대기열이 짧은 폴링 을 사용하도록 설정된 경우 서버의 하위 집합 만 쿼리 될 수 있습니다 . 내 생각 엔 당신이 부를 때 운 이 없었고 매번 돌아 왔을 receiveMessage뿐입니다 3.

동일한 문서 페이지에서 긴 폴링 의 이점을 살펴보면 다음과 같습니다.

긴 폴링은 다음과 같은 이점을 제공합니다.

  • 응답을 보내기 전에 대기열에서 메시지를 사용할 수있을 때까지 Amazon SQS가 대기하도록하여 빈 응답을 제거하십시오. 연결 시간이 초과되지 않으면 ReceiveMessage 요청에 대한 응답에는 사용 가능한 메시지 중 하나 이상 (ReceiveMessage 작업에 지정된 최대 메시지 수까지)이 포함됩니다.

  • Amazon SQS 서버의 하위 집합이 아닌 모든 항목을 쿼리하여 빈 응답을 제거합니다.

두 번째 총알은 여기서 매우 중요합니다. 빈 응답이 표시되지 않더라도 쿼리되지 않은 서버에 더 많은 메시지가 저장되어있을 수 있습니다. 긴 폴링을 사용하는 경우 총 3 대의 서버가 있다고 가정 할 때 리턴되는 메시지의 양이 증가하는 것을 알 수 있습니다.

따라서 큐에서 긴 폴링을 사용하는 것이 좋습니다. 이렇게하려면 긴 폴링 설정 페이지를 참조하십시오.


아래의 주석 에서 DevilCode가 언급했듯이 표준 대기열 대신 FIFO 대기열을 사용하고 긴 폴링을 사용하여 문제를 해결할 수있었습니다.


답변

나는 이것이 비슷한 질문 이라고 생각한다 .Jacob 지적했듯이 긴 폴링은이 문제에 대한 해결책 인 것 같습니다.


답변

긴 폴링 :

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


답변