我在SQS中有多条消息。以下代码始终仅返回一个,即使有几十个可见(不在飞行中)。 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
感谢您的输入
答案 0 :(得分:32)
AWS API Reference Guide: Query/QueryReceiveMessage
由于队列的分布式特性,在ReceiveMessage调用上对加权随机机器集进行采样。这意味着只返回采样机器上的消息。如果队列中的消息数量很少(小于1000),则可能会获得比每次ReceiveMessage调用请求的消息少的消息。如果队列中的消息数量非常小,您可能不会在特定的ReceiveMessage响应中收到任何消息;在这种情况下,您应该重复请求。
和
MaxNumberOfMessages :要返回的最大邮件数。 SQS永远不会返回比此值更多的消息,但可能会返回更少的。
答案 1 :(得分:8)
对SQS reference documentation中的这种(可以说是相当特殊的)行为有一个全面的解释。
SQS stores copies of messages on multiple servers并使用two possible strategies之一
接收对这些服务器的消息请求在实践中,对于我的有限测试,我似乎总是像你一样得到一条短轮询的消息。
答案 2 :(得分:4)
我遇到了同样的问题。您的队列设置的接收消息等待时间是多少?当我的时间为0时,即使队列中有8个,它也只返回1条消息。当我增加接收消息等待时间时,我得到了所有这些。对我来说似乎有点儿麻烦。
答案 3 :(得分:1)
receiveMessageRequest.withMaxNumberOfMessages(10);
为了清楚起见,更实际的用法是添加到你的构造函数中:
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl).withMaxNumberOfMessages(10);
否则,你可以这样做:
receiveMessageRequest.setMaxNumberOfMessages(10);
话虽如此,改变这一点对原来的问题没有帮助。
答案 4 :(得分:1)
我只是尝试了同样的事情,在这两个属性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
...
答案 5 :(得分:0)
感谢Caoilte!
我也遇到了这个问题。最后使用长轮询解决,请按照以下配置进行操作: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-configure-long-polling-for-queue.html
不幸的是,要使用长轮询,您必须将队列创建为FIFO 1。我没有运气就尝试了标准队列。
并且在接收时,还需要设置MaxNumberOfMessages。所以我的代码就像:
ReceiveMessageRequest receive_request =新的ReceiveMessageRequest() .withQueueUrl(QUEUE_URL) .withWaitTimeSeconds(20) .withMaxNumberOfMessages(10);
尽管解决了,但仍然感觉太有线了。 AWS绝对应该为这种基本的接收操作提供更简洁的API。
从我的角度来看,AWS具有许多很酷的功能,但没有好的API。就像那些家伙一直在赶时间。
答案 6 :(得分:0)
这是一种解决方法,您可以异步调用receiveMessageFromSQS方法。
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);
});
}
它将返回一个具有给定数量消息的数组
答案 7 :(得分:0)
对于小任务列表,我使用stackoverflow.com/a/55149351/13678017之类的FIFO队列 例如修改后的AWS tutorial
// Create a queue.
System.out.println("Creating a new Amazon SQS FIFO queue called " + "MyFifoQueue.fifo.\n");
final Map<String, String> attributes = new HashMap<>();
// A FIFO queue must have the FifoQueue attribute set to true.
attributes.put("FifoQueue", "true");
/*
* If the user doesn't provide a MessageDeduplicationId, generate a
* MessageDeduplicationId based on the content.
*/
attributes.put("ContentBasedDeduplication", "true");
// The FIFO queue name must end with the .fifo suffix.
final CreateQueueRequest createQueueRequest = new CreateQueueRequest("MyFifoQueue4.fifo")
.withAttributes(attributes);
final String myQueueUrl = sqs.createQueue(createQueueRequest).getQueueUrl();
// List all queues.
System.out.println("Listing all queues in your account.\n");
for (final String queueUrl : sqs.listQueues().getQueueUrls()) {
System.out.println(" QueueUrl: " + queueUrl);
}
System.out.println();
// Send a message.
System.out.println("Sending a message to MyQueue.\n");
for (int i = 0; i < 4; i++) {
var request = new SendMessageRequest()
.withQueueUrl(myQueueUrl)
.withMessageBody("message " + i)
.withMessageGroupId("userId1");
;
sqs.sendMessage(request);
}
for (int i = 0; i < 6; i++) {
var request = new SendMessageRequest()
.withQueueUrl(myQueueUrl)
.withMessageBody("message " + i)
.withMessageGroupId("userId2");
;
sqs.sendMessage(request);
}
// Receive messages.
System.out.println("Receiving messages from MyQueue.\n");
var receiveMessageRequest = new ReceiveMessageRequest(myQueueUrl);
receiveMessageRequest.setMaxNumberOfMessages(10);
receiveMessageRequest.setWaitTimeSeconds(20);
// what receive?
receiveMessageRequest.withMessageAttributeNames("userId2");
final List<Message> messages = sqs.receiveMessage(receiveMessageRequest).getMessages();
for (final 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 (final Entry<String, String> entry : message.getAttributes()
.entrySet()) {
System.out.println("Attribute");
System.out.println(" Name: " + entry
.getKey());
System.out.println(" Value: " + entry
.getValue());
}
}