SQS maxNumberOfMessages


11

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>

생각은했지만 AWS에서 대기열 자체의 구성을 확인 했습니까? 아마도 java 클라이언트에서 설정 한 것보다 우선 순위가 높은 maxNumberOfMessages 속성으로 설정되었을 수 있습니까? 그것이 자바 스크립트 람다에서 작동하기 때문에, 이것은 이상하지만, 여전히 가치가 있습니다 :)
niekname

답변:


9

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

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

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


긴 폴링

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

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

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

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

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

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

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

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

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


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


긴 폴링으로 동일한 테스트를 수행했으며 동일한 결과를 얻었습니다. 대기열에 12,000 개의 메시지가 있었고 폴링은 20 초로 설정되었습니다. 여전히 3 개의 메시지 만받습니다. 긴 폴링과 짧은 폴링을 가진 세 개의 메시지가 수신되면 긴 폴링을 사용할 이유가 없습니다 (큐가 비어있는 메시지 대기중인 경우 제외). 불행히도 우리는 비용과 속도의 균형을 맞추려고 노력하고 있습니다. 불행히도 (하드웨어로 인해) 사용할 수있는 읽기 스레드가 제한되어 있기 때문에 통화 당 풀다운 할 수있는 메시지 수는 처리 속도를 제한하는 요소입니다.
DevilCode

@DevilCode 긴 폴링이 활성화 된 상태에서 문제를 재현 할 수 없었습니다. 대기열이 표준 대기열입니까 아니면 FIFO 대기열입니까? AWS에서 지원 티켓을 열어서 최종 변경이 가능한지 확인할 수도 있습니다.
Jacob G.

표준 대기열입니다. 코드를 로컬로 실행하고 Java를 사용 했습니까?
DevilCode

@DevilCode FIFO 대기열을 사용하여 테스트했습니다. 그리고 예, AWS Java SDK v2를 사용하여 SQS 대기열에서 메시지를 수신하고 있습니다. 내 코드가 AWS Lambda 함수 내에서 실행되고 있지 않습니다.
Jacob G.

1
확인 FIFO 대기열을 테스트 한 결과 표준 대기열과 같이 3 개의 메시지 만 10 개의 메시지가 표시됩니다. 이제 결론을 내릴 수있는 것은 설명서가 표준 대기열이 아니라 FIFO 대기열을 참조한다는 것입니다.
DevilCode

0

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


0

긴 폴링 :

        ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl)
              .withWaitTimeSeconds(10)     // long poll: wait 10 seconds, max is 20 seconds
              .withMaxNumberOfMessages(10);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.