我有以下代码从SQS队列中检索消息。我使用AmazonSQSBufferedAsyncClient
从队列中检索消息。固定延迟SingleThreadedExecutor
每5分钟唤醒receiveMessage
。队列中启用了长轮询
@Service
public class AmazonQueueService
implements QueueService<String> {
@Autowired
private AmazonSQSBufferedAsyncClient sqsAsyncClient;
@Value("${aws.sqs.queueUrl}")
private String queueUrl;
@Override
public List<Message<String>> receiveMessage() {
ReceiveMessageRequest receiveMessageRequest = new ReceiveMessageRequest(queueUrl);
ReceiveMessageResult result = sqsAsyncClient.receiveMessage(receiveMessageRequest);
LOG.debug("Size=" + result.getMessages().size());
return Lists.transform(result.getMessages(), ......);
}
.....
}
问题是当我检查AWS控制台时,消息总是在飞行中,但在应用程序中从未收到(大小始终打印为0)。看起来AmazonSQSBufferedAsyncClient
正在从队列中读取消息但未在receiveMessage
调用中返回。
有什么想法吗?
答案 0 :(得分:4)
终于弄明白了。问题表现在队列可见性超时(2分钟)和scheduledExecutor延迟(5分钟)的组合。
将可见性超时增加到15分钟解决了这个问题。
我的理论是 - &gt; AmazonSQSBufferedAsyncClient检索消息并将其保留在等待receiveMessage调用的缓冲区中。由于执行程序延迟为5分钟,因此将调用消息的可见性,以便调用receiveMessage并将消息返回到队列。它看起来似乎几乎立即从队列中选择了消息。现在无论出于何种原因,对receiveMessage的调用都不会收到消息。在超时事件发生之前增加超时,这使得receiveMessage调用有机会发生,我想是解决了这个问题。
还有其他可能的解释吗?
答案 1 :(得分:2)
对我来说,问题是即使在控制台上看到它们之前,lambda仍在读取我的消息。因此,结果是我无法从sqs控制台轮询消息。
答案 2 :(得分:1)
完成后,您必须从队列中删除该消息。如果你不这样做,它将继续飞行,直到它超时,然后再回到队列。它以这种方式设计,因此您永远不会丢失消息。如果程序在完成处理消息并将其删除之前崩溃,则消息将立即返回队列。
来自基本Java example(SampleDriver.java
):
QMessage message = messages.get(0);
System.out.println("\nMessage received");
System.out.println(" message id: " + message.getId());
System.out.println(" receipt handle: " + message.getReceiptHandle());
System.out.println(" message content: " + message.getContent());
testQueue.deleteMessage(message.getReceiptHandle()); // <===== here