簡體   English   中英

AWS SQS Java。 並非所有消息都從SQS隊列中檢索

[英]AWS SQS Java. Not all messages are retrieved from the SQS queue

我一直在嘗試使用AWS SDK for Java從SQS隊列中檢索所有消息的幾種方法無濟於事。 我已經了解了AWS SQS的分布式特性,並且消息存儲在不同的服務器上。 但我不明白為什么這個架構不會被最終用戶隱藏。 我需要在Java代碼中應用哪些技巧來檢索所有消息,並且100%確定沒有人錯過?

我試着用“長輪詢”

ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
for (Message message : messages) {
System.out.println(" Message");
System.out.println(" MessageId: " + message.getMessageId());
System.out.println(" ReceiptHandle: " + message.getReceiptHandle());
System.out.println(" MD5OfBody: " + message.getMD5OfBody());
System.out.println(" Body: " + message.getBody());
for (Entry<String, String> entry : message.getAttributes().entrySet()) {
System.out.println(" Attribute");
System.out.println(" Name: " + entry.getKey());
System.out.println(" Value: " + entry.getValue());
}
}
System.out.println();

這與請求批處理/客戶端緩​​沖:

    // Create the basic Amazon SQS async client
    AmazonSQSAsync sqsAsync = new AmazonSQSAsyncClient();

    // Create the buffered client
    AmazonSQSAsync bufferedSqs = new AmazonSQSBufferedAsyncClient(sqsAsync);

    CreateQueueRequest createRequest = new CreateQueueRequest().withQueueName("MyTestQueue");

    CreateQueueResult res = bufferedSqs.createQueue(createRequest);

    SendMessageRequest request = new SendMessageRequest();
    String body = "test message_" + System.currentTimeMillis();
    request.setMessageBody( body );
    request.setQueueUrl(res.getQueueUrl());

    SendMessageResult sendResult = bufferedSqs.sendMessage(request);

    ReceiveMessageRequest receiveRq = new ReceiveMessageRequest()
    .withMaxNumberOfMessages(10)
    .withQueueUrl(queueUrl);
    ReceiveMessageResult rx = bufferedSqs.receiveMessage(receiveRq);

    List<Message> messages = rx.getMessages();
    for (Message message : messages) {
    System.out.println(" Message");
    System.out.println(" MessageId: " + message.getMessageId());
    System.out.println(" ReceiptHandle: " + message.getReceiptHandle());
    System.out.println(" MD5OfBody: " + message.getMD5OfBody());
    System.out.println(" Body: " + message.getBody());
    for (Entry<String, String> entry : message.getAttributes().entrySet()) {
    System.out.println(" Attribute");
    System.out.println(" Name: " + entry.getKey());
    System.out.println(" Value: " + entry.getValue());
    }
    }

但我仍然無法檢索所有消息。

任何想法?

AWS論壇對我的帖子保持沉默。

從SQS隊列接收消息時,需要重復調​​用sqs:ReceiveMessage

在每次調用sqs:ReceiveMessage ,您將從隊列中獲得0個或更多消息,您需要迭代這些消息。 對於每條消息,您還需要調用sqs:DeleteMessage ,以便在處理sqs:DeleteMessage消息后從隊列中刪除消息。

在上面的“長輪詢”示例周圍添加一個循環以接收所有消息。

for (;;) {
    ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
    List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
    for (Message message : messages) {
        System.out.println(" Message");
        System.out.println(" MessageId: " + message.getMessageId());
        System.out.println(" ReceiptHandle: " + message.getReceiptHandle());
        System.out.println(" MD5OfBody: " + message.getMD5OfBody());
        System.out.println(" Body: " + message.getBody());
        for (Entry<String, String> entry : message.getAttributes().entrySet()) {
            System.out.println(" Attribute");
            System.out.println(" Name: " + entry.getKey());
            System.out.println(" Value: " + entry.getValue());
        }
    }
    System.out.println();
}

另請注意,您可能會多次收到相同的消息。 因此,允許您的工作“重新處理”相同的消息,或檢測重復的消息。

我也面臨同樣的問題 - 只有一條消息被返回,然后我嘗試了receiveMessageRequest.setMaxNumberOfMessages(10),這將幫助我在一個循環中檢索10條消息,

因為我的隊列有> 500條記錄,我所做的就是

    List<String> messagelist = new ArrayList<>();

    try
    {
        AmazonSQS sqs = new AmazonSQSClient(credentials);
        Region usWest2 = Region.getRegion(Regions.US_WEST_2);
        sqs.setRegion(usWest2);
        boolean flag = true;

        while(flag)
        {
            ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queuename);
            receiveMessageRequest.setMaxNumberOfMessages(number_of_message_);
            receiveMessageRequest.withMaxNumberOfMessages(number_of_message_).withWaitTimeSeconds(wait_time_second_);
            List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();

            for (Message message : messages) 
                  {
                    //   System.out.println("    Body:          " + message.getBody());
                       messagelist.add( message.getBody());

                       String messageReceiptHandle = message.getReceiptHandle();
                       sqs.deleteMessage(new DeleteMessageRequest().withQueueUrl(queuename).withReceiptHandle(messageReceiptHandle));
                    }
            if(messages.size()==0)
            {
                flag = false;
            }
        }         

    }
    catch (AmazonServiceException ase) {
        ase.printStackTrace();
    } catch (AmazonClientException ace) {
       ace.printStackTrace();
    }
    finally {
        return messagelist ;
    }

我正在從SQS讀取記錄,然后將其保存到String列表中,然后從隊列中刪除記錄。

所以最后我將列表中的隊列中的所有數據

如果隊列中沒有消息,則長輪詢將等待。 這意味着如果您使用循環中的長輪詢調用ReceiveMessage,則可以保證您將獲得所有消息。 當響應中收到0條消息時,您已收到所有消息。

您提到您還使用了Web控制台。 Web控制台的工作方式與使用SDK調用API的方式相同。 這意味着當您在控制台中接收和查看消息時,消息對其他客戶端是不可見的,直到可見性超時到期為止。 這可能是你沒有看到消息的原因。

查看有關可見性超時的更多信息

http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html

SQS隊列不是數據庫。 您無法將所有消息讀入列表中,就像您嘗試做的那樣。 隊列沒有開始也沒有結束。 您輪詢隊列並詢問一些消息,它會返回一些消息(如果存在)。

如果你想要一個可以返回整個數據集的方法,那么sqs就不是正確的工具 - 在這種情況下,傳統的數據庫可能會更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM