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と新しいaws sdkの両方を使用して、Javaで2つのクライアントをテストしたところ、同じ結果が得られました。常に3つのメッセージのみが返されます。

興味深いことに、アプリケーションを外部(私の強力なデスクトップ上)で実行する代わりに、AWS Lambdaとして実行すると、10のメッセージが表示されます。このラムダテストは、同僚がJavaScriptを使用して行ったものです。

したがって、疑問が残るのは、なぜ要求ごとに3つのメッセージしか取得せず、ラムダ内で10を取得できるように見えるのかということです。

リクエストあたりのコストがあるとすると、Amazonの利益に基づいて重み付けされたランダム分布になります=))

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プロパティでセットアップされましたか?javascriptラムダで動作するので、これは奇妙ですが、まだ
試してみる

回答:


9

リクエストあたりのコストがあるとすると、Amazonの利益に基づいて重み付けされたランダム分布になります=))

ここでの目標は、SQSに送信する要求を少なくするか、SQSに使用可能なメッセージの最大量を強制的に配信することによって、コストを削減することであることは明らかです。

あなたの質問で述べたように、SQSは利用可能なメッセージの最大量を配信する義務はありません。ただし、まだ気付いていない場合に備えてお知らせしたいことがあります。


ロングポーリング

開発者ガイド Amazonのシンプルなキューサービス状態の:

キューからメッセージを消費するプロセスは、ショートポーリングとロングポーリングのどちらを使用するかによって異なります。デフォルトでは、Amazon SQSはショートポーリングを使用し、(重み付けランダム分布に基づいて)サーバーのサブセットのみをクエリして、応答に使用できるメッセージがあるかどうかを判断します。あなたは使用することができ、長いポーリングを彼らがキューに到着するとすぐにメッセージを受信するために、あなたの消費者を可能にしながら、あなたのコストを削減します。

SQSに送信したメッセージは、すべて別のサーバーに格納されている可能性があります。ドキュメントに記載されているように、キューがショートポーリングを使用するように設定されている場合、クエリできるのはサーバーのサブセットのみです。私の推測では、あなたは呼び出し時に不運であり、毎回receiveMessageのみ3返されたと思います。

同じドキュメントページでロングポーリングの利点を見ると、次のように述べられています。

ロングポーリングには次の利点があります。

  • Amazon SQSがメッセージをキューで使用できるようになるまで待機してから応答を送信できるようにすることで、空の応答を排除します。接続がタイムアウトしない限り、ReceiveMessage要求への応答には、ReceiveMessageアクションで指定されたメッセージの最大数まで、少なくとも1つの使用可能なメッセージが含まれます。

  • Amazon SQSサーバーのサブセットではなく、すべてにクエリを実行して、空の誤った応答を排除します。

ここでは2番目の箇条書きが非常に重要です。空の応答は表示されていませんが、クエリされていないサーバーに保存されているメッセージがまだ残っている可能性があります。ロングポーリングを有効にすると、合計で3台を超えるサーバーがあると想定して、返されるメッセージの量が増加するはずです。

したがって、私の提案は、キューでロングポーリングを有効にすることです。これを行うには、ロングポーリング設定ページを参照してください。


以下のコメントで DevilCodeが述べたように、彼は標準キューの代わりにFIFOキューを使用し、それに対してロングポーリングを有効にすることで問題を解決することができました。


ロングポーリングで同じことをテストし、同じ結果を得ました。キューには12,000のメッセージがあり、ポーリングは20秒に設定されています。まだ3つのメッセージしか受け取りません。長いポーリングと短いポーリングの3つのメッセージを受け取った場合、長いポーリングを使用する理由はありません(メッセージを待機しているキューが空である場合を除きます)。残念ながら、コストとスピードのバランスをとろうとしています。残念ながら、(ハードウェアにより)使用できる読み取りスレッドは限られているため、コールごとにプルダウンできるメッセージの数は、処理できる速度を制限する要因です。
DevilCode

@DevilCodeロングポーリングを有効にした状態で問題を再現できませんでした。キューは標準キューですか、それともFIFOキューですか?また、AWSでサポートチケットを開いて、彼らが自分の側で変更を加えることができるかどうかを確認することもできます。
Jacob G.

標準のキューです。コードをローカルで実行し、Javaを使用していましたか?
DevilCode

@DevilCode FIFOキューを使用してテストしました。はい、私はAWS Java SDK v2を使用してSQSキューからメッセージを受信して​​います。AWS Lambda関数内でコードが実行されていません。
Jacob G.

1
OK FIFOキューをテストすると、10個のメッセージが表示されますが、標準のキューと同様に3つしか表示されません。ここで結論付けられるのは、ドキュメントが標準のキューではなくFIFOキューを参照しているということだけです。
DevilCode

0

これは同様の質問だと思います。ジェイコブが指摘したように、ロングポーリングは問題の解決策のようです。


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.