web-dev-qa-db-ja.com

SQSから複数のメッセージを取得する

SQSに複数のメッセージがあります。次のコードalwaysは、数十が表示されていても(飛行中ではない)、1つだけを返します。 setMaxNumberOfMessages 一度に複数を消費できると思いました..これを誤解していませんか?

 CreateQueueRequest createQueueRequest = new CreateQueueRequest().withQueueName(queueName);
 String queueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
 ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl);
 receiveMessageRequest.setMaxNumberOfMessages(10);
 List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
 for (Message message : messages) {
      // i'm a message from SQS
 }

私も withMaxNumberOfMessages を使用してみましたが、そのような運はありません:

 receiveMessageRequest.withMaxNumberOfMessages(10);

キューにメッセージがあることをどのようにして知ることができますか? 1以上?

 Set<String> attrs = new HashSet<String>();
 attrs.add("ApproximateNumberOfMessages");
 CreateQueueRequest createQueueRequest = new CreateQueueRequest().withQueueName(queueName);
 GetQueueAttributesRequest a = new GetQueueAttributesRequest().withQueueUrl(sqs.createQueue(createQueueRequest).getQueueUrl()).withAttributeNames(attrs);
 Map<String,String> result = sqs.getQueueAttributes(a).getAttributes();
 int num = Integer.parseInt(result.get("ApproximateNumberOfMessages"));

上記は常に前に実行され、int> 1

あなたの入力をありがとう

27
sdolgy

AWS APIリファレンスガイド:Query/QueryReceiveMessage

キューは分散されているため、ReceiveMessage呼び出しで、重み付けされたランダムなマシンのセットがサンプリングされます。つまり、サンプリングされたマシンのメッセージのみが返されます。キュー内のメッセージ数が少ない(1000未満)場合は、ReceiveMessage呼び出しごとに要求した数よりも少ないメッセージを取得する可能性があります。キュー内のメッセージ数が非常に少ない場合、特定のReceiveMessage応答でメッセージを受信できない可能性があります。その場合は、リクエストを繰り返す必要があります。

そして

MaxNumberOfMessages:返すメッセージの最大数。 SQSはこの値より多くのメッセージを返すことはありませんが、返す数が少ない場合があります。

32
sdolgy

SQSリファレンスドキュメント に、この(おそらくかなり特異な)動作の包括的な説明があります。

SQSはメッセージのコピーを複数のサーバーに保存します であり、受信メッセージ要求はこれらのサーバーに対して 2つの可能な戦略 のいずれかで行われます。

  • ショートポーリング:デフォルトの動作、サーバーのサブセットのみ(加重ランダム分布に基づく)が照会されます
  • ロングポーリング:WaitTimeSeconds属性をゼロ以外の値に設定することで有効になり、すべてのサーバーが照会されます

実際には、限られたテストでは、あなたと同じように、短いポーリングで常に1つのメッセージを受け取るようです。

8
Caoilte

私も同じ問題を抱えていました。キューの受信メッセージ待機時間は何に設定されていますか?鉱山が0の場合、キューに8があったとしても、1つのメッセージしか返しませんでした。メッセージ受信待機時間を増やしたところ、すべてが取得されました。ちょっとバギーのようです。

4
wisbucky

私は同じことを試していましたが、これらの2つの属性setMaxNumberOfMessagesとsetWaitTimeSecondsを使用して、10個のメッセージを取得できました。

ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
                      receiveMessageRequest.setMaxNumberOfMessages(10);
                      receiveMessageRequest.setWaitTimeSeconds(20);

O/pのスナップショット:

Receiving messages from TestQueue.
Number of messages:10
Message
MessageId:     31a7c669-1f0c-4bf1-b18b-c7fa31f4e82d 
...
3
niranjan

receiveMessageRequest.withMaxNumberOfMessages(10);

明確にするために、これをより実用的に使用するには、次のようにコンストラクタに追加します。

ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl).withMaxNumberOfMessages(10);

それ以外の場合は、次のようにします。

receiveMessageRequest.setMaxNumberOfMessages(10);

そうは言っても、これを変更しても元の問題は解決しません。

1
Marcus

Caoilte、ありがとう!

私もこの問題に直面しました。最後に、ロングポーリングを使用して解決し、次の構成に従います。 https://docs.aws.Amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-long-polling-for-queue.html

残念ながら、ロングポーリングを使用するには、FIFO one。

受信時には、MaxNumberOfMessagesも設定する必要があります。だから私のコードは次のようなものです:

ReceiveMessageRequest receive_request = new ReceiveMessageRequest().withQueueUrl(QUEUE_URL).withWaitTimeSeconds(20).withMaxNumberOfMessages(10);

解決しましたが、まだあまりにも有線に感じています。 AWSは、この種の基本的な受信操作のためにより明確なAPIを提供する必要があります。

私の考えでは、AWSには多くの優れた機能がありますが、優れたAPIではありません。それらの人がいつも急いでいるように。

0
muyong

その回避策として、ReceiveMessageメソッドを非同期に呼び出すことができます。

   bulkReceiveFromSQS (queueUrl, totalMessages, asyncLimit, batchSize, visibilityTimeout, waitTime, callback) {
    batchSize = Math.min(batchSize, 10);

    let self = this,
        noOfIterations = Math.ceil(totalMessages / batchSize);

    async.timesLimit(noOfIterations, asyncLimit, function(n, next) {
        self.receiveMessageFromSQS(queueUrl, batchSize, visibilityTimeout, waitTime,
            function(err, result) {
                if (err) {
                    return next(err);
                }

                return next(null, _.get(result, 'Messages'));
            });
    }, function (err, listOfMessages) {
        if (err) {
            return callback(err);
        }
        listOfMessages = _.flatten(listOfMessages).filter(Boolean);

        return callback(null, listOfMessages);
    });
}

メッセージの制限数を尋ねられたメッセージの配列を返します。

0
Amit