AWS SQS Java。并非所有消息都从SQS队列中检索

时间:2015-06-24 12:59:21

标签: java amazon-web-services amazon-sqs

我一直在尝试使用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论坛对我的帖子保持沉默。

4 个答案:

答案 0 :(得分:9)

从SQS队列接收消息时,您需要重复呼叫sqs:ReceiveMessage

在每次调用sqs:ReceiveMessage时,您将从队列中获得0条或更多条消息,您需要迭代这些消息。对于每条消息,当您处理完每封邮件时,您还需要致电sqs:DeleteMessage以从队列中删除邮件。

在你的&#34;长轮询&#34;周围添加一个循环以上示例以接收所有消息。

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();
}

另请注意,您可能会多次收到相同的讯息。因此,让您的工作进行&#34;重新处理&#34;相同的消息,或检测重复的消息。

答案 1 :(得分:2)

我也面临同样的问题 - 只有一条消息被退回,然后我试过了 receiveMessageRequest.setMaxNumberOfMessages(10),它可以帮助我在循环中检索10条消息,

因为我的队列有> 500条记录我所做的是

TEST.framework

我正在从SQS读取记录,然后将其保存到字符串列表中,然后从队列中删除记录。

所以最后我将把队列中的所有数据都放在一个列表中

答案 2 :(得分:0)

如果队列中没有消息,则长轮询将等待。这意味着如果您使用循环中的长轮询调用ReceiveMessage,则可以保证您将获得所有消息。当收到0条消息作为回应时,您已收到所有消息。

您提到您还使用了Web控制台。 Web控制台的工作方式与使用SDK调用API的方式相同。这意味着当您在控制台中接收和查看消息时,消息对其他客户端是不可见的,直到可见性超时到期为止。这可能是您没有看到消息的原因。

查看有关可见性超时的更多信息:

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

答案 3 :(得分:0)

SQS队列不是数据库。您无法将所有消息读入列表中,就像您尝试做的那样。队列没有开始也没有结束。您轮询队列并询问一些消息,如果它们存在,它会返回一些消息。

如果你想要一个可以返回整个数据集的方法,那么sqs不是正确的工具 - 在这种情况下传统的数据库可能会更好。